diff --git a/.github/workflows/codestyle.yml b/.github/workflows/codestyle.yml index 736b5b853b72..ce17062ba976 100644 --- a/.github/workflows/codestyle.yml +++ b/.github/workflows/codestyle.yml @@ -16,7 +16,7 @@ on: [pull_request] jobs: checkpatch: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false @@ -33,7 +33,7 @@ jobs: # depth 2 so: # ^1. we can show the Subject of the current target branch tip # ^2. we reconnect/graft to the later fetch pull/1234/head, - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: {fetch-depth: 2} - name: install codespell @@ -56,7 +56,7 @@ jobs: yamllint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: run yamllint # Quoting to please all parsers is hard. This indirection helps. diff --git a/.github/workflows/installer.yml b/.github/workflows/installer.yml index b3f6d3f5848e..655603af0c83 100644 --- a/.github/workflows/installer.yml +++ b/.github/workflows/installer.yml @@ -17,18 +17,17 @@ on: [push, pull_request, workflow_dispatch] jobs: checktree: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: # just a vector in this case make_env: [ - IPC_VERSION=, # default version - IPC_VERSION=IPC4 UNSIGNED_list= SIGNED_list='tgl tgl-h', + IPC_VERSION= UNSIGNED_list='imx8' SIGNED_list=, # default version ] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # From time to time this will catch a git tag and change SOF_VERSION with: {fetch-depth: 50, submodules: recursive} diff --git a/.github/workflows/ipc_fuzzer.yml b/.github/workflows/ipc_fuzzer.yml index b19cade4180e..8d3ca974c073 100644 --- a/.github/workflows/ipc_fuzzer.yml +++ b/.github/workflows/ipc_fuzzer.yml @@ -8,59 +8,43 @@ name: IPC fuzzing # yamllint disable-line rule:truthy on: [pull_request, workflow_dispatch] - -# For the actual fuzzer see tools/oss-fuzz/README. -# also see -# https://google.github.io/oss-fuzz/getting-started/continuous-integration/ -# -# Build and run fuzzer for 5s just to check that it runs properly. If it -# consistently fails in under 5s you probably did something wrong - -# If you came here to quickly copy/paste the invocation of some build -# script in order to reproduce a failure reported by github then you -# will be disappointed by the Github Action below: it's magical. For a -# thorough reproduction you must follow the links above. For a quick, -# dirty and incomplete reproduction hack you can try the following two -# lines. Don't do this at home. -# -# OUT=unused_dir cmake -B oss-fuzz-build/ -S tools/oss-fuzz/ -# make -j -C oss-fuzz-build sof_ep fuzz_ipc.o jobs: - ipc-fuzzer-build: - runs-on: ubuntu-latest - steps: - - name: Build Fuzzers - uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master - with: - oss-fuzz-project-name: 'sound-open-firmware' - - - name: Run Fuzzers - uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master - with: - oss-fuzz-project-name: 'sound-open-firmware' - language: c - fuzz-seconds: 5 - - # TODO, to add IPC4 support fix compilation of: - # - # ./scripts/fuzz.sh -t 1 -- -DCONFIG_IPC_MAJOR_4=y - # - # ... or of some other _IPC4_ -DOVERLAY_CONFIG= - # - # Then use a simple IPC3/IPC4 matrix like the one in zephyr.yml - simple-IPC3-fuzz_sh: + simple-IPC-fuzz_sh: runs-on: ubuntu-22.04 + strategy: + fail-fast: false + matrix: + # Keep these names short due to questionable Github UI choices + IPC: [IPC3, IPC4] + steps: - name: add i386 arch run: | sudo dpkg --add-architecture i386 sudo apt-get update - - name: apt-get install - run: sudo apt-get update && sudo apt-get -y install - clang llvm libc6-dev-i386 libstdc++-12-dev:i386 - ninja-build device-tree-compiler python3-pyelftools + - name: apt-get install i386 packages + run: | + + # We don't know why Github requires us to explicit all these i386 + # dependencies. On a vanilla Ubuntu 22.04 the last apt-get is + # enough. + # Also, it does not seem possible to download Github images for + # local testing which means trial and error for this requires a + # force-push every time: excruciatingly slow! + sudo apt-get -y install \ + libgcc-s1:i386 libc6-dev:i386 libstdc++6:i386 \ + libgomp1:i386 libitm1:i386 libatomic1:i386 \ + libasan8:i386 libubsan1:i386 libquadmath0:i386 \ + + sudo apt-get -y install \ + libc6-dev-i386 libstdc++-12-dev:i386 + + - name: apt-get install build tools + run: + sudo apt-get -y install + clang llvm ninja-build device-tree-compiler python3-pyelftools - uses: actions/checkout@v3 with: @@ -78,4 +62,8 @@ jobs: cd workspace clang --verbose set -x - sof/scripts/fuzz.sh -o _.log -t 300 + case '${{ matrix.IPC }}' in + IPC3) cmake_arg='-DCONFIG_IPC_MAJOR_3=y' ;; + IPC4) cmake_arg='-DCONFIG_IPC_MAJOR_4=y' ;; + esac + sof/scripts/fuzz.sh -o _.log -t 300 -- "$cmake_arg" diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index b39c11b87fdc..90ae5e511c92 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -9,7 +9,7 @@ # github.com also has a powerful web editor that can be used without # committing. -# TODO: finishing scattering this very old workflow to more specific +# TODO: finish scattering this very old workflow to more specific # .yml files name: Main Actions @@ -118,7 +118,7 @@ jobs: gcc-build-only: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false @@ -127,7 +127,6 @@ jobs: # to COMMAS. Don't use a single big group so a single failure # does not block all other builds. platform: [imx8ulp, - tgl, rn rmb, mt8186 mt8195, ] @@ -154,7 +153,7 @@ jobs: # duplication. qemu-boot-test: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false diff --git a/.github/workflows/repro-build.yml b/.github/workflows/repro-build.yml index c3090154b608..fde2bed91486 100644 --- a/.github/workflows/repro-build.yml +++ b/.github/workflows/repro-build.yml @@ -16,10 +16,10 @@ on: [pull_request] jobs: main: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: {fetch-depth: 5, submodules: recursive} - name: docker pull diff --git a/.github/workflows/sparse-zephyr.yml b/.github/workflows/sparse-zephyr.yml index 80eab54c4635..a0e7c8f3a0e7 100644 --- a/.github/workflows/sparse-zephyr.yml +++ b/.github/workflows/sparse-zephyr.yml @@ -15,27 +15,14 @@ jobs: # sof/scripts/parse_sparse_output.sh warnings-subset: - # We're sharing binaries with the zephyr-build container so keep + # We're sharing the sparse binary with the zephyr-build container so keep # this in sync with it. - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: - platforms: [ - {platform: tgl, - real_cc: xtensa-intel_s1000_zephyr-elf/bin/xtensa-intel_s1000_zephyr-elf-gcc}, - # This is the WRONG compiler for MTL but for now this is the - # one and only one expected by the Zephyr build system so it - # must be set to this value to sparse MTL. - # Sparse needs a REAL_CC but it does not matter which one, it - # does not affect sparse results. - # As soon as sof/west.yml is updated to a fixed Zephyr version - # this will fail with an error message that will show the - # exact value that must replace this one. - {platform: mtl, - real_cc: xtensa-intel_s1000_zephyr-elf/bin/xtensa-intel_s1000_zephyr-elf-gcc}, - ] + platform: [tgl, mtl, lnl] steps: - name: git clone sparse analyzer @@ -67,22 +54,16 @@ jobs: - name: Download docker image && ls /opt/toolchains/ run: cd workspace && ./sof/zephyr/docker-run.sh ls -l /opt/toolchains/ - # We have to painfully extract REAL_CC from the docker image to - # tell the Zephyr build what it... already knows and wants!! Zephyr - # commit 3ebb18b8826 explains this sparse problem. - # # --pristine is important to reproduce _warnings_. It makes no # difference for github but it's useful for anyone trying to # reproduce and copying the command from the logs. - name: analyze zephyr working-directory: ./workspace run: | - ./sof/zephyr/docker-run.sh /bin/sh -c \ - 'cmake -P ./sof/zephyr/FindZephyr-sdk.cmake > zsdk_location' - cat zsdk_location - ZSDK=$(cat zsdk_location); _RCC=${{ matrix.platforms.real_cc }} - REAL_CC="$ZSDK/$_RCC" ./sof/zephyr/docker-run.sh \ - ./sof/zephyr/docker-build.sh ${{ matrix.platforms.platform }} \ - --cmake-args=-DSPARSE=y --pristine 2>&1 | tee _.log + ./sof/zephyr/docker-run.sh \ + ./sof/zephyr/docker-build.sh ${{ matrix.platform }} \ + --cmake-args=-DZEPHYR_SCA_VARIANT=sparse --cmake-args=-DCONFIG_LOG_USE_VLA=n \ + --pristine 2>&1 | tee _.log + printf '\n\n\t\t\t ---- Messages below are treated as sparse errors --- \n\n\n' (set -x; ./sof/scripts/parse_sparse_output.sh ${{ matrix.platforms.platform }} <_.log) diff --git a/.github/workflows/testbench.yml b/.github/workflows/testbench.yml index 326c8be3f1f9..6f668753e0d0 100644 --- a/.github/workflows/testbench.yml +++ b/.github/workflows/testbench.yml @@ -33,7 +33,7 @@ jobs: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: {fetch-depth: 5} - name: apt get diff --git a/.github/workflows/tools.yml b/.github/workflows/tools.yml index 5be87125a8ba..670d67ad9627 100644 --- a/.github/workflows/tools.yml +++ b/.github/workflows/tools.yml @@ -12,7 +12,7 @@ jobs: top-level_default_CMake_target_ALL: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 # The ALSA version in Ubuntu 20.04 is buggy # (https://github.com/thesofproject/sof/issues/2543) and likely diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 9bbe004092ea..bc1619fda3b5 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -14,7 +14,7 @@ jobs: cmocka_utests: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: {fetch-depth: 2} - name: build and run all defconfigs diff --git a/.github/workflows/zephyr.yml b/.github/workflows/zephyr.yml index ff310851154d..4c2974bf6584 100644 --- a/.github/workflows/zephyr.yml +++ b/.github/workflows/zephyr.yml @@ -59,10 +59,16 @@ jobs: fi build-linux: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: + # These keys are kept short because Github's left column is not resizable. + # Search "zephyr_revision" and see below what they expand to. + zephyr_revision: [ + mnfst, # special value: don't override sof/west.yml + zmain, # Zephyr's main branch + ] # Using groups to avoid spamming the small results box with too # many lines. Pay attention to COMMAS. IPC_platforms: [ @@ -70,14 +76,18 @@ jobs: imx8 imx8x imx8m, tgl tgl-h, # UNSUPPORTED! Will be removed # - IPC4 default - mtl, + mtl, lnl, # Temporary testbed for Zephyr development. -i IPC4 tgl tgl-h, ] - zephyr_revision: [ - manifest_revision, - "https://github.com/zephyrproject-rtos/zephyr main", - ] + build_opts: [""] + # Sparse matrices are complicated, you must read this page slowly: + # https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs + include: + # specify one extra -d combination without affecting the main matrix + - build_opts: -d + zephyr_revision: mnfst + IPC_platforms: mtl steps: - uses: actions/checkout@v3 @@ -88,35 +98,36 @@ jobs: fetch-depth: 0 path: ./workspace/sof - # As of December 2022 `--shallow-exclude=v3.2.0-rc3` fixes `git - # describe`, Zephyr's version.h and build reproducibility while - # downloading about 200MB less compared to a full clone. - # - # Ideally, the --shallow-exclude= argument should be regularly - # bumped whenever SOF upgrades Zephyr to keep this as fast as - # possible. - # In a bigger Zephyr future maybe we could move to a more permanent - # git fetch --shallow-since='5 months ago' because Zephyr follows - # a "roughly 4-month release" but for now that saves only 100MB - # https://docs.zephyrproject.org/latest/project/release_process.html - # - # TODO: try replacing --narrow and --depth with some - # --fetch-opt=--filter=? - # https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/ - name: west clones # Get some git tags in Zephyr. keep in sync with build-windows below run: pip3 install west && cd workspace/sof/ && west init -l && - west update --narrow --fetch-opt=--depth=5 && - git -C ../zephyr fetch --shallow-exclude=v3.2.0-rc3 + west update --narrow --fetch-opt=--filter=tree:0 - name: select zephyr revision - run: cd workspace/zephyr/ && - if [ 'manifest_revision' != '${{ matrix.zephyr_revision }}' ]; then - git fetch ${{ matrix.zephyr_revision }} && - git checkout FETCH_HEAD; - fi && - git log --oneline -n 5 --decorate --graph --no-abbrev-commit + run: | + cd workspace + if [ 'mnfst' != '${{ matrix.zephyr_revision }}' ]; then + case '${{ matrix.zephyr_revision }}' in + 'zmain') rem_rev='main' ;; + *) echo 'Unknown matrix.zephyr_revision'; exit 1 ;; + esac + ( cd sof/submanifests/ + sed -e "s#=sof_zephyr_revision_override=#${rem_rev}#" \ + sof-ci-jenkins/zephyr-override-template.yml > test-zephyr-main.yml + ) + west update --narrow --fetch-opt=--filter=tree:0 + # For some unknown reason `west` fetches using the literal remote URL + # which breaks --decorate. Maybe zephyrproject-rtos/west/pull/346 has + # some relevant background? For now `west` uses the remote name + # `zephyrproject`, use that knowledge to fix --decorate but ignore any + # failure in case the name changes or some other issue. + git -C zephyr/ fetch '--filter=tree:0' zephyrproject "${rem_rev}" || true + fi + set -x + west list + west status + git -C zephyr/ log --oneline -n 5 --decorate --graph --no-abbrev-commit # Not strictly necessary but saves a lot of scrolling in the next step # Caching a 12G image is unfortunately not possible: @@ -131,13 +142,15 @@ jobs: - name: build run: cd workspace && ./sof/zephyr/docker-run.sh ./sof/zephyr/docker-build.sh --cmake-args=-DEXTRA_CFLAGS=-Werror - --cmake-args=--warn-uninitialized ${{ matrix.IPC_platforms }} + --cmake-args=-DEXTRA_AFLAGS='-Werror -Wa,--fatal-warnings' + --cmake-args=--warn-uninitialized + ${{ matrix.build_opts }} ${{ matrix.IPC_platforms }} - name: Upload build artifacts uses: actions/upload-artifact@v3 - if: ${{ matrix.zephyr_revision == 'manifest_revision' }} + if: ${{ matrix.zephyr_revision == 'mnfst' }} with: - name: linux-build ${{ matrix.IPC_platforms }} + name: linux-build ${{ matrix.build_opts }} ${{ matrix.IPC_platforms }} path: | ${{ github.workspace }}/workspace/build-sof-staging ${{ github.workspace }}/workspace/**/compile_commands.json @@ -146,7 +159,6 @@ jobs: runs-on: windows-latest strategy: fail-fast: false - # FIXME: Create common matrix for build-linux and build-windows matrix: # Using groups to avoid spamming the small results box with too # many lines. Pay attention to COMMAS. @@ -159,6 +171,13 @@ jobs: # Very few IPC3 platforms support IPC4 too. -i IPC4 tgl tgl-h, ] + build_opts: [""] + # Sparse matrices are complicated, see comments on Linux matrix above. + include: + - build_opts: -d + zephyr_revsion: mnfst + platforms: mtl + steps: - uses: actions/checkout@v3 @@ -185,19 +204,12 @@ jobs: # Keep this SDK version identical to the one in # sof/zephyr/docker-run.sh - - name: Cache Zephyr SDK 0.15.2 + - name: Cache Zephyr SDK 0.16.1 id: cache-zephyr-sdk uses: actions/cache@v3.0.11 with: - path: zephyr-sdk-0.15.2_windows-x86_64.zip - key: ${{ runner.os }}-cache-zephyr-sdk-0-15-2 - - # Unzip is needed by Zephyr SDK setup.cmd installation script - - name: Download unzip - if: ${{ steps.cache-unzip.outputs.cache-hit != 'true' }} - run: | - curl -L -o unzip-5.51-1-bin.zip ` - https://gnuwin32.sourceforge.net/downlinks/unzip-bin-zip.php + path: zephyr-sdk-0.16.1_windows-x86_64.7z + key: ${{ runner.os }}-cache-zephyr-sdk-0-16-1 # Wget is needed by Zephyr SDK setup.cmd installation script - name: Download wget @@ -205,15 +217,17 @@ jobs: run: | curl -L -O http://downloads.sourceforge.net/gnuwin32/wget-1.11.4-1-bin.zip - - name: Download Zephyr SDK 0.15.2 + - name: Download Zephyr SDK 0.16.1 if: ${{ steps.cache-zephyr-sdk.outputs.cache-hit != 'true' }} run: | # yamllint disable-line rule:line-length curl -L -O ` - https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.15.2/zephyr-sdk-0.15.2_windows-x86_64.zip + https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.1/zephyr-sdk-0.16.1_windows-x86_64.7z # Unzips every .zip package to directory matching its name without extension - name: Unzip downloaded packages - run: 7z x *.zip -o* + run: | + 7z x *.zip -o* + 7z x *.7z -o* - name: Add unzip to system PATH run: | @@ -230,7 +244,7 @@ jobs: # setup.cmd may not be called in from msys shell as it does not parse # forward slash script input arguments correctly. - name: Install Zephyr SDK - run: zephyr-sdk-0.15.2_windows-x86_64/zephyr-sdk-0.15.2/setup.cmd /t all /h /c + run: zephyr-sdk-0.16.1_windows-x86_64/zephyr-sdk-0.16.1/setup.cmd /t all /h /c - name: Setup Python uses: actions/setup-python@v4 @@ -244,8 +258,7 @@ jobs: working-directory: ${{ github.workspace }}/workspace # Keep in sync with build-linux above run: west init -l sof && - west update --narrow --fetch-opt=--depth=5 && - git -C zephyr fetch --shallow-exclude=v3.2.0-rc3 + west update --narrow --fetch-opt=--filter=tree:0 # Call Setup Python again to save the PIP packages in cache - name: Setup Python @@ -275,12 +288,13 @@ jobs: run: python sof/scripts/xtensa-build-zephyr.py --no-interactive --cmake-args=-DEXTRA_CFLAGS=-Werror - --cmake-args=--warn-uninitialized ${{ matrix.platforms }} + --cmake-args=-DEXTRA_AFLAGS='-Werror -Wa,--fatal-warnings' + --cmake-args=--warn-uninitialized ${{ matrix.build_opts }} ${{ matrix.platforms }} - name: Upload build artifacts uses: actions/upload-artifact@v3 with: - name: windows-build ${{ matrix.platforms}} + name: windows-build ${{ matrix.build_opts }} ${{ matrix.platforms }} path: | ${{ github.workspace }}/workspace/build-sof-staging ${{ github.workspace }}/workspace/**/compile_commands.json @@ -321,8 +335,18 @@ jobs: - name: Compare Linux vs Windows builds run: | - # FIXME: for windows the Z_SDK version is hardcoded above, for Linux it's not. - diffs=0 + diffs=0; ls -l + + # Check not too much is missing (it happened!) + # http://mywiki.wooledge.org/ParsingLs + for regdir in 'linux-build *mtl' \ + 'windows-build *mtl' \ + 'windows-build *-i IPC4 tgl tgl-h'; do + find . -maxdepth 1 | grep -q "\./${regdir}\$" || + { >&2 printf 'Missing %s\n' "${regdir}"; exit 1; } + done + + set -x for windir in windows-build*; do lindir=linux-"${windir#windows-}" diff -qr "$lindir" "$windir" || : $((diffs++)) diff --git a/.gitmodules b/.gitmodules index 73f77e1ab704..da3426a76e3d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,19 @@ [submodule "rimage"] path = rimage +# This is a _relative_ submodule URL. In some use cases it's better than +# an _absolute_ submodule URL, in other cases it's not. One size does +# unfortunately not fit all. +# +# Among other pages, http://blog.tremily.us/posts/Relative_submodules/ +# has a good comparison +# +# If you use Zephyr you must also look at the comments in sof/west.yml. +# +# If you want to fork or mirror sof.git _without_ doing the same for +# rimage.git then your automation may want you to change and git commit +# an absolute URL in your branch. No need to git commit for interactive +# use; a local and temporary edit of this file is enough for interactive +# use because .gitmodules is used only once to --init[ialize] +# .git/config the first time. Then .gitmodules is never used again after +# cloning. url = ../rimage diff --git a/CODEOWNERS b/CODEOWNERS index affaaf29dc4b..421903647c40 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -65,7 +65,7 @@ src/math/* @singalsu src/ipc/* @bardliao @marcinszkudlinski @pblaszko @aborisovich src/lib/* @libinyang src/debug/gdb/* @abonislawski -src/schedule @pblaszko @marcinszkudlinski +src/schedule @pblaszko @marcinszkudlinski @dbaluta @LaurentiuM1234 # samples samples/audio/detect_test.c @iganakov diff --git a/Kconfig.sof b/Kconfig.sof index 22b16af9d036..453c5348b8dd 100644 --- a/Kconfig.sof +++ b/Kconfig.sof @@ -11,10 +11,6 @@ config HOST_PTABLE bool default n -config XT_BOOT_LOADER - bool - default n - config XT_HAVE_RESET_VECTOR_ROM bool default n diff --git a/app/boards/intel_adsp_ace20_lnl.conf b/app/boards/intel_adsp_ace20_lnl.conf new file mode 100644 index 000000000000..11a9026008de --- /dev/null +++ b/app/boards/intel_adsp_ace20_lnl.conf @@ -0,0 +1,76 @@ +CONFIG_LUNARLAKE=y +CONFIG_IPC_MAJOR_4=y + +# turn off SOF drivers +CONFIG_INTEL_DMIC=n +CONFIG_INTEL_DMIC_NHLT=n +CONFIG_INTEL_SSP=n +CONFIG_INTEL_ALH=n +CONFIG_COMP_SRC=y + +CONFIG_COMP_SRC_IPC4_FULL_MATRIX=y + +# power settings +CONFIG_PM=y +CONFIG_PM_DEVICE=y +CONFIG_PM_DEVICE_RUNTIME=y +CONFIG_PM_DEVICE_POWER_DOMAIN=y +CONFIG_PM_POLICY_CUSTOM=y + +CONFIG_POWER_DOMAIN=y +CONFIG_POWER_DOMAIN_INTEL_ADSP=y + +# enable Zephyr drivers +CONFIG_ZEPHYR_NATIVE_DRIVERS=y +CONFIG_DAI=y +CONFIG_DAI_INIT_PRIORITY=70 +CONFIG_DAI_INTEL_DMIC=y +CONFIG_DAI_DMIC_HW_IOCLK=38400000 +CONFIG_DAI_INTEL_DMIC_NHLT=y +CONFIG_DAI_DMIC_HAS_OWNERSHIP=n +CONFIG_DAI_DMIC_HAS_MULTIPLE_LINE_SYNC=y +CONFIG_DAI_INTEL_SSP=y +CONFIG_ZEPHYR_DP_SCHEDULER=y +CONFIG_DMA=y +CONFIG_DMA_INTEL_ADSP_GPDMA=n +CONFIG_DMA_DW_SUSPEND_DRAIN=y +CONFIG_INTEL_MODULES=y +CONFIG_LIBRARY_MANAGER=y +CONFIG_INTEL_ADSP_TIMER=y +CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM=y +CONFIG_AMS=y +CONFIG_COUNTER=y + +CONFIG_HEAP_MEM_POOL_SIZE=8192 +CONFIG_L3_HEAP=y +CONFIG_RIMAGE_SIGNING_SCHEMA="lnl" + +CONFIG_FORMAT_CONVERT_HIFI3=n +CONFIG_PCM_CONVERTER_FORMAT_S16_C16_AND_S16_C32=y +CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S32_C32=y +CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S24_C32=y +CONFIG_PCM_CONVERTER_FORMAT_S24_C24_AND_S24_C32=y +CONFIG_PCM_CONVERTER_FORMAT_S24_C32_AND_S24_C24=y +CONFIG_PCM_CONVERTER_FORMAT_S16_C32_AND_S16_C32=y +CONFIG_LOG=y +CONFIG_LOG_MODE_DEFERRED=y +CONFIG_LOG_FUNC_NAME_PREFIX_INF=y +CONFIG_COMP_VOLUME_WINDOWS_FADE=y +CONFIG_COMP_UP_DOWN_MIXER=y +CONFIG_COMP_CHAIN_DMA=y +CONFIG_SYS_CLOCK_TICKS_PER_SEC=12000 +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=38400000 + +CONFIG_LOG_BACKEND_ADSP_MTRACE=y +CONFIG_SOF_LOG_LEVEL_INF=y +CONFIG_ZEPHYR_LOG=y + +CONFIG_INTEL_ADSP_IPC=y + + +# Temporary disabled options +CONFIG_TRACE=n +CONFIG_COMP_KPB=y +CONFIG_COMP_ARIA=y +CONFIG_CLOCK_CONTROL_ADSP=y +CONFIG_CLOCK_CONTROL=y diff --git a/app/boards/mimx93_evk_a55_sof.conf b/app/boards/mimx93_evk_a55_sof.conf new file mode 100644 index 000000000000..0452c6598b19 --- /dev/null +++ b/app/boards/mimx93_evk_a55_sof.conf @@ -0,0 +1,2 @@ +CONFIG_IMX93_A55=y +CONFIG_TRACE=n diff --git a/app/overlays/lnl/fpga_overlay.conf b/app/overlays/lnl/fpga_overlay.conf new file mode 100644 index 000000000000..0fc3ac375789 --- /dev/null +++ b/app/overlays/lnl/fpga_overlay.conf @@ -0,0 +1,2 @@ +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=19200000 +CONFIG_DAI_DMIC_HW_IOCLK=19200000 diff --git a/app/src/main.c b/app/src/main.c index 156893f5fbe3..7a622556b1ae 100644 --- a/app/src/main.c +++ b/app/src/main.c @@ -20,7 +20,7 @@ int sof_main(int argc, char *argv[]); * TODO: Here comes SOF initialization */ -void main(void) +int main(void) { int ret; @@ -47,4 +47,5 @@ void main(void) */ k_thread_suspend(k_current_get()); #endif + return 0; } diff --git a/installer/GNUmakefile b/installer/GNUmakefile index 3e854143cb71..3caaab5eb3b5 100644 --- a/installer/GNUmakefile +++ b/installer/GNUmakefile @@ -14,14 +14,11 @@ # List of /lib/firmware/sof/ images and symbolic links currently # released by Intel. -# See rimage/config/*.toml -SIGNED_list ?= tgl tgl-h - # To find aliases, try in a Linux kernel git clone: # # git grep 'sof-.*\.ri' -- sound/soc/ -ALIAS_OTHER_KEY_list += adl adl-s rpl rpl-s +# ALIAS_OTHER_KEY_list += adl adl-s rpl rpl-s # Not supported in the main branch anymore, go to stable-v2.3 # UNSIGNED_list += bdw byt cht @@ -39,11 +36,7 @@ $(info UNSIGNED_list = ${UNSIGNED_list} ) $(info SIGNED_list = ${SIGNED_list} ) $(info ALIAS_list = ${ALIAS_list} ) -target_of_ehl := tgl -target_of_adl := tgl -target_of_adl-s := tgl-h -target_of_rpl := tgl -target_of_rpl-s := tgl-h +target_of_imx := imx8 ifeq (,${TOOLCHAIN}) ifeq (,${XTENSA_TOOLS_ROOT}) diff --git a/installer/tests/staging_sof_ref.txt b/installer/tests/staging_sof_ref.txt index 2cad7d207e4b..0029924ddd40 100644 --- a/installer/tests/staging_sof_ref.txt +++ b/installer/tests/staging_sof_ref.txt @@ -1,23 +1,5 @@ . -├── community -│   ├── sof-adl-s.ri -> sof-tgl-h.ri -│   ├── sof-adl.ri -> sof-tgl.ri -│   ├── sof-rpl-s.ri -> sof-tgl-h.ri -│   ├── sof-rpl.ri -> sof-tgl.ri -│   ├── sof-tgl-h.ri -│   └── sof-tgl.ri -├── intel-signed -├── sof-adl-s.ldc -> sof-tgl-h.ldc -├── sof-adl-s.ri -> intel-signed/sof-adl-s.ri -├── sof-adl.ldc -> sof-tgl.ldc -├── sof-adl.ri -> intel-signed/sof-adl.ri -├── sof-rpl-s.ldc -> sof-tgl-h.ldc -├── sof-rpl-s.ri -> intel-signed/sof-rpl-s.ri -├── sof-rpl.ldc -> sof-tgl.ldc -├── sof-rpl.ri -> intel-signed/sof-rpl.ri -├── sof-tgl-h.ldc -├── sof-tgl-h.ri -> intel-signed/sof-tgl-h.ri -├── sof-tgl.ldc -└── sof-tgl.ri -> intel-signed/sof-tgl.ri +├── sof-imx8.ldc +└── sof-imx8.ri -2 directories, 18 files +0 directories, 2 files diff --git a/lmdk/README.md b/lmdk/README.md new file mode 100644 index 000000000000..874171826189 --- /dev/null +++ b/lmdk/README.md @@ -0,0 +1,17 @@ +# Loadable Modules Dev Kit + +***TODO: add link to the documentation repo!*** + +To build dummy loadable library execute: + + cd libraries/dummy + cmake -B build -G -DRIMAGE_INSTALL_DIR="path/where/rimage/executable/is" -DSNIGNING_KEY="path/to/key" + cd --build build + + +Here RIMAGE_INSTALL_DIR is a path to directory where rimage executable is, SIGNING_KEY is a path to +signing key for rimage. If RIMAGE_INSTALL_DIR is not provided, rimage will be searched for in the directory +where SOF project installs it. Dummy module sets up toolchain file in the project file. +However, in your library you can select toolchain file in the configure step command: + + cmake -B build -G --toolchain "../../cmake/xtensa-toolchain.cmake" -DSNIGNING_KEY="path/to/key" diff --git a/lmdk/cmake/build.cmake b/lmdk/cmake/build.cmake new file mode 100644 index 000000000000..e3182f596b06 --- /dev/null +++ b/lmdk/cmake/build.cmake @@ -0,0 +1,67 @@ +# This file is intended to be included from project's CMakeLists.txt. +# Prior to include, MODULES_LIST variable should be initialised with list +# of modules (subdirectories in modules dir) that should be built into +# project's loadable library. + +if(NOT DEFINED MODULES_LIST) + message(FATAL_ERROR "Please define MODULES_LIST: list of modules to be built into loadable library") +endif() + +include(${CMAKE_CURRENT_LIST_DIR}/config.cmake) + +foreach(MODULE ${MODULES_LIST}) + add_executable(${MODULE}) + add_subdirectory(${LMDK_BASE}/modules/${MODULE} ${MODULE}_module) + +### set_target_properties(${MODULE} PROPERTIES OUTPUT_NAME ${MODULE}.mod) + + target_include_directories(${MODULE} PRIVATE + "${LMDK_BASE}/include" + "${RIMAGE_INCLUDE_DIR}" + ) + + # generate linker script + get_target_property(HPSRAM_ADDR ${MODULE} HPSRAM_ADDR) + + if(NOT DEFINED HPSRAM_ADDR) + message(FATAL_ERROR "Please define HPSRAM_ADDR for module ${MODULE}") + endif() + + add_custom_command(TARGET ${MODULE} PRE_LINK + COMMAND ${CMAKE_COMMAND} + -DMODULE=${MODULE} + -DHPSRAM_ADDR=${HPSRAM_ADDR} + -P ${CMAKE_CURRENT_LIST_DIR}/ldscripts.cmake + ) + + target_link_options(${MODULE} PRIVATE + "-nostdlib" "-nodefaultlibs" + "-Wl,--no-undefined" "-Wl,--unresolved-symbols=report-all" "-Wl,--error-unresolved-symbols" + #"-Wl,--gc-sections" # may remove .bss and that will result in rimage error, do not use for now + "-Wl,-Map,$.map" # optional: just for debug + "-T" "${MODULE}_ldscripts/elf32xtensa.x" + ) +endforeach() + +set(RIMAGE_OUTPUT_FILE ${PROJECT_NAME}_noextmft) +set(OUTPUT_FILE ${PROJECT_NAME}.bin) + +if(RIMAGE_INSTALL_DIR) + cmake_path(ABSOLUTE_PATH RIMAGE_INSTALL_DIR BASE_DIRECTORY ${CMAKE_SOURCE_DIR} NORMALIZE) +endif() + +# Create a hint - rimage may be installed to directory where SOF project installs it +cmake_path(APPEND SOF_BASE "../build-rimage" OUTPUT_VARIABLE RIMAGE_SOF_INSTALL_DIR) +cmake_path(NORMAL_PATH RIMAGE_SOF_INSTALL_DIR) +cmake_path(ABSOLUTE_PATH SIGNING_KEY BASE_DIRECTORY ${CMAKE_SOURCE_DIR} NORMALIZE) + +find_program(RIMAGE_COMMAND NAMES rimage + PATHS "${RIMAGE_INSTALL_DIR}" + HINTS "${RIMAGE_SOF_INSTALL_DIR}" + REQUIRED) + +add_custom_target(${PROJECT_NAME}_target ALL + DEPENDS ${MODULES_LIST} + COMMAND ${RIMAGE_COMMAND} -k ${SIGNING_KEY} -f 2.0.0 -b 1 -o ${RIMAGE_OUTPUT_FILE} -c ${TOML} -e ${MODULES_LIST} + COMMAND ${CMAKE_COMMAND} -E cat ${RIMAGE_OUTPUT_FILE}.xman ${RIMAGE_OUTPUT_FILE} > ${OUTPUT_FILE} +) diff --git a/lmdk/cmake/config.cmake b/lmdk/cmake/config.cmake new file mode 100644 index 000000000000..5c7305c05133 --- /dev/null +++ b/lmdk/cmake/config.cmake @@ -0,0 +1,18 @@ + +if(NOT DEFINED SIGNING_KEY) + message(FATAL_ERROR + " Please define SIGNING_KEY: path to signing key for rimage.\n" + " E.g. using cmake -DSIGNING_KEY=/path/to/key.pem command line parameter." + ) +endif() + +# This Loadable Modules Dev Kit root dir +set(LMDK_BASE ${CMAKE_CURRENT_LIST_DIR}/..) +cmake_path(ABSOLUTE_PATH LMDK_BASE NORMALIZE) + +# thesofproject root dir +set(SOF_BASE ${LMDK_BASE}/..) +cmake_path(ABSOLUTE_PATH SOF_BASE NORMALIZE) + +set(RIMAGE_INCLUDE_DIR ${SOF_BASE}/rimage/src/include) +cmake_path(ABSOLUTE_PATH RIMAGE_INCLUDE_DIR NORMALIZE) diff --git a/lmdk/cmake/ldscripts.cmake b/lmdk/cmake/ldscripts.cmake new file mode 100644 index 000000000000..4d99b99a8492 --- /dev/null +++ b/lmdk/cmake/ldscripts.cmake @@ -0,0 +1,49 @@ +# Linker scripts generator + +# These linker scripts are based on those found in https://github.com/thesofproject/converged-sof-modules +# +# There are few things these scripts ensure: +# +# (1) Each module has its own reserved (virtual) address space. This is specified as +# HPSRAM_ADDR in module's CMakeLists.txt and goes to memory_header_linker_script.txt. +# +# (2) .buildinfo section must be put at 0 offset of .text section. .buildinfo contains +# module loadable libraries API version. That API version is verified by base FW. +# Base FW accesses it simply as 0 offset from module's code. +# +# (3) .module section contains module manifest description. This section is used by +# rimage to generate module manifest. Scripts ensure that this section is not garbage +# collected by linker. + +# Required parameters MODULE and HPSRAM_ADDR should be specified in command line. + +if(NOT DEFINED MODULE) + message(FATAL_ERROR "MODULE not defined") +endif() + +if(NOT DEFINED HPSRAM_ADDR) + message(FATAL_ERROR "HPSRAM_ADDR not defined") +endif() + +# reserve space for manifest? +math(EXPR HPSRAM "${HPSRAM_ADDR} + 9 * 4096" OUTPUT_FORMAT HEXADECIMAL) + +set(LDSCRIPTS_DIR ${MODULE}_ldscripts) +set(LDSCRIPT_FILE ${LDSCRIPTS_DIR}/elf32xtensa.x) + +file(MAKE_DIRECTORY ${LDSCRIPTS_DIR}) +file(WRITE ${LDSCRIPT_FILE} "") + +file(APPEND ${LDSCRIPT_FILE} "INCLUDE ${CMAKE_CURRENT_BINARY_DIR}/${LDSCRIPTS_DIR}/memory_header_linker_script.txt\n") +configure_file( + ${CMAKE_CURRENT_LIST_DIR}/ldscripts/memory_header_linker_script.txt.in + ${CMAKE_CURRENT_BINARY_DIR}/${LDSCRIPTS_DIR}/memory_header_linker_script.txt +) + +file(APPEND ${LDSCRIPT_FILE} "INCLUDE ${CMAKE_CURRENT_LIST_DIR}/ldscripts/text_linker_script.txt\n") +file(APPEND ${LDSCRIPT_FILE} "INCLUDE ${CMAKE_CURRENT_LIST_DIR}/ldscripts/common_text_linker_script.txt\n") +file(APPEND ${LDSCRIPT_FILE} "INCLUDE ${CMAKE_CURRENT_LIST_DIR}/ldscripts/data_linker_script.txt\n") +file(APPEND ${LDSCRIPT_FILE} "INCLUDE ${CMAKE_CURRENT_LIST_DIR}/ldscripts/common_rodata_linker_script.txt\n") +file(APPEND ${LDSCRIPT_FILE} "INCLUDE ${CMAKE_CURRENT_LIST_DIR}/ldscripts/bss_linker_script.txt\n") +file(APPEND ${LDSCRIPT_FILE} "INCLUDE ${CMAKE_CURRENT_LIST_DIR}/ldscripts/xt_linker_script.txt\n") +file(APPEND ${LDSCRIPT_FILE} "INCLUDE ${CMAKE_CURRENT_LIST_DIR}/ldscripts/guard_linker_script.txt\n") diff --git a/lmdk/cmake/ldscripts/bss_linker_script.txt b/lmdk/cmake/ldscripts/bss_linker_script.txt new file mode 100644 index 000000000000..c214d4662978 --- /dev/null +++ b/lmdk/cmake/ldscripts/bss_linker_script.txt @@ -0,0 +1,20 @@ + +PHDRS { + bss_phdr PT_LOAD; +} + +SECTIONS { + max_instances = 1; + max_instances-1 = max_instances - 1; + + .bss (NOLOAD) : ALIGN(4096) { + _first_start = ABSOLUTE(.); + *(.first) + _first_end = ABSOLUTE(.); + _next_start = ABSOLUTE(.); + . += (_first_end - _first_start) * max_instances-1; + _next_end = ABSOLUTE(.); + *(.bss) + *(.bss.*) + } >HPSRAM_seg : bss_phdr +} diff --git a/lmdk/cmake/ldscripts/common_rodata_linker_script.txt b/lmdk/cmake/ldscripts/common_rodata_linker_script.txt new file mode 100644 index 000000000000..2f3e4bfad4d9 --- /dev/null +++ b/lmdk/cmake/ldscripts/common_rodata_linker_script.txt @@ -0,0 +1,38 @@ + +PHDRS { + rodata_phdr PT_LOAD; +} + +SECTIONS { + .common.rodata : ALIGN(4096) { + _rodata_start = ABSOLUTE(.); + *(.rodata) + *(.rodata.*) + *(.rodata1) + __XT_EXCEPTION_TABLE__ = ABSOLUTE(.); + KEEP (*(.xt_except_table)) + KEEP (*(.gcc_except_table)) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + KEEP (*(.eh_frame)) + /* C++ constructor and destructor tables properly ordered: */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS__ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + . = ALIGN(4); /* this table MUST be 4-byte aligned */ + _rodata_end = ABSOLUTE(.); + } >HPSRAM_seg : rodata_phdr +} diff --git a/lmdk/cmake/ldscripts/common_text_linker_script.txt b/lmdk/cmake/ldscripts/common_text_linker_script.txt new file mode 100644 index 000000000000..10468dc4bf3a --- /dev/null +++ b/lmdk/cmake/ldscripts/common_text_linker_script.txt @@ -0,0 +1,24 @@ + +PHDRS { + text_phdr PT_LOAD; +} + +SECTIONS { + .common.text : ALIGN(4096){ + _common_text_start = ABSOLUTE(.); + *(.entry.text) + *(.init.literal) + KEEP(*(.init)) + *(.literal .text) + *(.literal.* .text.*) + *(.stub) + *(.gnu.warning) + *(.gnu.linkonce.literal*) + *(.gnu.linkonce.t.*.literal*) + *(.gnu.linkonce.t*) + *(.fini.literal) + KEEP(*(.fini)) + *(.gnu.version) + _common_text_end = ABSOLUTE(.); + } >HPSRAM_seg : text_phdr +} diff --git a/lmdk/cmake/ldscripts/data_linker_script.txt b/lmdk/cmake/ldscripts/data_linker_script.txt new file mode 100644 index 000000000000..08b75bbf5b53 --- /dev/null +++ b/lmdk/cmake/ldscripts/data_linker_script.txt @@ -0,0 +1,30 @@ + +PHDRS { + data_phdr PT_LOAD; + rodata_phdr PT_LOAD; +} + +EXTERN(HPSRAM) + +SECTIONS { + .data : ALIGN(4096) { + _data_start = ABSOLUTE(.); + *(.data) + *(.data.*) + _data_end = ABSOLUTE(.); + } >HPSRAM_seg : data_phdr + + .rodata : ALIGN(4096) { + _rodata_start = ABSOLUTE(.); + *(.gnu.linkonce.r.*) + *(.rodata) + *(.rodata.*) + KEEP (*(.eh_frame)) + _rodata_end = ABSOLUTE(.); + } >HPSRAM_seg : rodata_phdr + + /* Module manifest is here */ + .module : ALIGN(4096) { + KEEP(*(.module)) + } >HPSRAM_seg : rodata_phdr +} diff --git a/lmdk/cmake/ldscripts/guard_linker_script.txt b/lmdk/cmake/ldscripts/guard_linker_script.txt new file mode 100644 index 000000000000..4d0ea5f03dbe --- /dev/null +++ b/lmdk/cmake/ldscripts/guard_linker_script.txt @@ -0,0 +1,12 @@ + +PHDRS { + guard_phdr PT_LOAD; +} + +SECTIONS { + .guard : ALIGN(4096) { + _guard_section_start = ABSOLUTE(.); + *(.*) + _guard_section_end = ABSOLUTE(.); + } >HPSRAM_seg : guard_phdr +} diff --git a/lmdk/cmake/ldscripts/memory_header_linker_script.txt.in b/lmdk/cmake/ldscripts/memory_header_linker_script.txt.in new file mode 100644 index 000000000000..c505a503c2fb --- /dev/null +++ b/lmdk/cmake/ldscripts/memory_header_linker_script.txt.in @@ -0,0 +1,8 @@ + +MEMORY { + HPSRAM_seg : org = ${HPSRAM}, len = 0xFFFFFFFF +} + +PHDRS { + HPSRAM_phdr PT_LOAD; +} diff --git a/lmdk/cmake/ldscripts/text_linker_script.txt b/lmdk/cmake/ldscripts/text_linker_script.txt new file mode 100644 index 000000000000..cd4412efccae --- /dev/null +++ b/lmdk/cmake/ldscripts/text_linker_script.txt @@ -0,0 +1,31 @@ + +/* EXTERN(${PACKAGE_ENTRY_POINT}) */ + +PHDRS { + text_phdr PT_LOAD; + cmi_text_phdr PT_LOAD; +} + +/* .buildinfo should be put at the beginning of .text segment! API version is defined there. */ + +SECTIONS { + .text : ALIGN(4096) { + _text_start = ABSOLUTE(.); + *(.buildinfo) + *(.gnu.linkonce.literal.*) + *(.gnu.linkonce.lit4) + *(.literal) + *(.literal.*) + *(.gnu.linkonce.t*) + *(.text) + *(.text.*) + *(.cmi.literal) + _text_end = ABSOLUTE(.); + } >HPSRAM_seg : text_phdr + + .cmi.text : ALIGN(4096) { + _cmi_text_start = ABSOLUTE(.); + *(.cmi.text) + _cmi_text_end = ABSOLUTE(.); + } >HPSRAM_seg : cmi_text_phdr +} diff --git a/lmdk/cmake/ldscripts/xt_linker_script.txt b/lmdk/cmake/ldscripts/xt_linker_script.txt new file mode 100644 index 000000000000..75137467376f --- /dev/null +++ b/lmdk/cmake/ldscripts/xt_linker_script.txt @@ -0,0 +1,55 @@ + +SECTIONS { + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + .xtensa.info 0 : { *(.xtensa.info) } + .comment 0 : { *(.comment) } + .debug_ranges 0 : { *(.debug_ranges) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + .xt.insn 0 : + { + KEEP (*(.xt.insn)) + KEEP (*(.gnu.linkonce.x.*)) + } + .xt.prop 0 : + { + KEEP (*(.xt.prop)) + KEEP (*(.xt.prop.*)) + KEEP (*(.gnu.linkonce.prop.*)) + } + .xt.lit 0 : + { + KEEP (*(.xt.lit)) + KEEP (*(.xt.lit.*)) + KEEP (*(.gnu.linkonce.p.*)) + } + .xt.profile_range 0 : + { + KEEP (*(.xt.profile_range)) + KEEP (*(.gnu.linkonce.profile_range.*)) + } + .xt.profile_ranges 0 : + { + KEEP (*(.xt.profile_ranges)) + KEEP (*(.gnu.linkonce.xt.profile_ranges.*)) + } + .xt.profile_files 0 : + { + KEEP (*(.xt.profile_files)) + KEEP (*(.gnu.linkonce.xt.profile_files.*)) + } +} diff --git a/lmdk/cmake/xtensa-toolchain.cmake b/lmdk/cmake/xtensa-toolchain.cmake new file mode 100644 index 000000000000..c5058b331ad4 --- /dev/null +++ b/lmdk/cmake/xtensa-toolchain.cmake @@ -0,0 +1,51 @@ +# Xtensa CMake toolchain file. Apply it using CMAKE_TOOLCHAIN_FILE variable. + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_VERSION 1) + +set(CMAKE_TRY_COMPILE_PLATFORM_VARIABLES XTENSA_TOOLCHAIN_PATH) + +if(NOT XTENSA_TOOLCHAIN_PATH) + set(XTENSA_TOOLCHAIN_PATH $ENV{XTENSA_TOOLCHAIN_PATH}) +endif() + +if(NOT XTENSA_TOOLCHAIN_PATH) + message(FATAL_ERROR "Failed to find Xtensa toolchain: XTENSA_TOOLCHAIN_PATH (env or CMake) variable not defined.") +endif() + +cmake_path(CONVERT ${XTENSA_TOOLCHAIN_PATH} TO_CMAKE_PATH_LIST XTENSA_TOOLCHAIN_PATH) +cmake_path(APPEND XTENSA_TOOLCHAIN_PATH "XtensaTools" OUTPUT_VARIABLE TOOLCHAIN_BASE) +set(CROSS_COMPILE xt-) + +# clang or xcc +find_program(CMAKE_C_COMPILER NAMES ${CROSS_COMPILE}xcc + PATHS ${TOOLCHAIN_BASE} PATH_SUFFIXES "bin" REQUIRED NO_DEFAULT_PATH +) +# clang++ or xc++ +find_program(CMAKE_CXX_COMPILER NAMES ${CROSS_COMPILE}xc++ + PATHS ${TOOLCHAIN_BASE} PATH_SUFFIXES "bin" REQUIRED NO_DEFAULT_PATH +) +find_program(CMAKE_LD NAMES ${CROSS_COMPILE}ld + PATHS ${TOOLCHAIN_BASE} PATH_SUFFIXES "bin" REQUIRED NO_DEFAULT_PATH +) +find_program(CMAKE_AR NAMES ${CROSS_COMPILE}ar + PATHS ${TOOLCHAIN_BASE} PATH_SUFFIXES "bin" REQUIRED NO_DEFAULT_PATH +) +find_program(CMAKE_RANLIB NAMES ${CROSS_COMPILE}ranlib + PATHS ${TOOLCHAIN_BASE} PATH_SUFFIXES "bin" REQUIRED NO_DEFAULT_PATH +) +find_program(CMAKE_OBJCOPY NAMES ${CROSS_COMPILE}objcopy + PATHS ${TOOLCHAIN_BASE} PATH_SUFFIXES "bin" REQUIRED NO_DEFAULT_PATH +) +find_program(CMAKE_OBJDUMP NAMES ${CROSS_COMPILE}objdump + PATHS ${TOOLCHAIN_BASE} PATH_SUFFIXES "bin" REQUIRED NO_DEFAULT_PATH +) +find_program(CMAKE_NM NAMES ${CROSS_COMPILE}nm + PATHS ${TOOLCHAIN_BASE} PATH_SUFFIXES "bin" REQUIRED NO_DEFAULT_PATH +) + +cmake_path(APPEND TOOLCHAIN_BASE "xtensa-elf" OUTPUT_VARIABLE XTENSA_ELF_ROOT) +set(CMAKE_FIND_ROOT_PATH ${XTENSA_ELF_ROOT}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) diff --git a/lmdk/include/todo.txt b/lmdk/include/todo.txt new file mode 100644 index 000000000000..83011e8c8236 --- /dev/null +++ b/lmdk/include/todo.txt @@ -0,0 +1 @@ +TODO: add SOF Loadable Modules Dev Kit headers here \ No newline at end of file diff --git a/lmdk/libraries/dummy/CMakeLists.txt b/lmdk/libraries/dummy/CMakeLists.txt new file mode 100644 index 000000000000..32cbd134dfae --- /dev/null +++ b/lmdk/libraries/dummy/CMakeLists.txt @@ -0,0 +1,19 @@ + +cmake_minimum_required(VERSION 3.20) +set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_LIST_DIR}/../../cmake/xtensa-toolchain.cmake") + +project(dummy) + +# list of modules to be built and included into this loadable library +set(MODULES_LIST dummy) + +# toml file for rimage to generate manifets +set(TOML "${CMAKE_CURRENT_LIST_DIR}/dummy_mtl.toml") + +# TODO: Move it somewhere?! This probably should be defined in some API header file! +# SOF loadable modules API version +add_definitions(-DMAJOR_IADSP_API_VERSION=5) +add_definitions(-DMIDDLE_IADSP_API_VERSION=0) +add_definitions(-DMINOR_IADSP_API_VERSION=0) + +include(../../cmake/build.cmake) diff --git a/lmdk/libraries/dummy/dummy_mtl.toml b/lmdk/libraries/dummy/dummy_mtl.toml new file mode 100644 index 000000000000..7f984d2a2382 --- /dev/null +++ b/lmdk/libraries/dummy/dummy_mtl.toml @@ -0,0 +1,86 @@ +version = [3, 0] + +[adsp] +name = "mtl" +image_size = "0x2C0000" # (22) bank * 128KB +alias_mask = "0xE0000000" + +[[adsp.mem_zone]] +type = "ROM" +base = "0x1FF80000" +size = "0x400" +[[adsp.mem_zone]] +type = "IMR" +base = "0xA104A000" +size = "0x2000" +[[adsp.mem_zone]] +type = "SRAM" +base = "0xa00f0000" +size = "0x100000" + +[[adsp.mem_alias]] +type = "uncached" +base = "0x40000000" +[[adsp.mem_alias]] +type = "cached" +base = "0xA0000000" + +[cse] +partition_name = "ADSP" +[[cse.entry]] +name = "ADSP.man" +offset = "0x5c" +length = "0x464" +[[cse.entry]] +name = "ADSP.met" +offset = "0x4c0" +length = "0x70" +[[cse.entry]] +name = "ADSP" +offset = "0x540" +length = "0x0" # calculated by rimage + +[css] + +[signed_pkg] +name = "ADSP" +partition_usage = "0x23" +[[signed_pkg.module]] +name = "ADSP.met" + +[adsp_file] +[[adsp_file.comp]] +base_offset = "0x2000" + +[fw_desc.header] +name = "ADSPFW" +load_offset = "0x40000" + +[module] +count = 1 + + [[module.entry]] + name = "DUMMY" + uuid = "01010101-0101-0101-0101-010101010101" + affinity_mask = "0x1" + instance_count = "15" + domain_types = "0" + load_type = "0" + module_type = "5" + auto_start = "0" + sched_caps = [1, 0x00008000] + + # pin = [dir, type, sample rate, size, container, channel-cfg] + pin = [0, 0, 0xffff, 0xc, 0x8, 0x05ff, + 1, 0, 0xffff, 0xc, 0x8, 0x45ff] + + # mod_cfg [PAR_0 PAR_1 PAR_2 PAR_3 IS_BYTES CPS IBS OBS MOD_FLAGS CPC OBLS] + mod_cfg = [0, 0, 0, 0, 216, 706000, 12, 16, 0, 0, 0, + 1, 0, 0, 0, 216, 1271000, 8, 8, 0, 0, 0, + 2, 0, 0, 0, 216, 1839000, 89, 118, 0, 0, 0, + 3, 0, 0, 0, 216, 2435000, 48, 64, 0, 0, 0, + 4, 0, 0, 0, 216, 3343000, 192, 192, 0, 0, 0, + 5, 0, 0, 0, 216, 3961000, 177, 177, 0, 0, 0, + 6, 0, 0, 0, 216, 4238000, 192, 256, 0, 0, 0, + 7, 0, 0, 0, 216, 6691000, 192, 256, 0, 0, 0] + diff --git a/lmdk/modules/dummy/CMakeLists.txt b/lmdk/modules/dummy/CMakeLists.txt new file mode 100644 index 000000000000..1ede12ca1445 --- /dev/null +++ b/lmdk/modules/dummy/CMakeLists.txt @@ -0,0 +1,6 @@ + +target_sources(dummy PRIVATE dummy.c) + +set_target_properties(dummy PROPERTIES + HPSRAM_ADDR "0xa06a1000" +) diff --git a/lmdk/modules/dummy/dummy.c b/lmdk/modules/dummy/dummy.c new file mode 100644 index 000000000000..3d8b3e787f07 --- /dev/null +++ b/lmdk/modules/dummy/dummy.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright 2023 Intel Corporation. All rights reserved. + +#include + +/* rimage fails if no .bss section found */ +int bss_workaround; + +#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) +{ + /* supposed to return here a pointer to module interface implementation */ + return (void *)0x12345678; +} + +__attribute__((section(".module"))) +const struct sof_man_module_manifest dummy_module_manifest = { + .module = { + .name = "DUMMY", + .uuid = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, + .entry_point = (uint32_t)dummyPackageEntryPoint, + .type = { + .load_type = SOF_MAN_MOD_TYPE_MODULE, + .domain_ll = 1 + }, + .affinity_mask = 3, + } +}; diff --git a/rimage b/rimage index 9643a986dda9..ab0429fdbe56 160000 --- a/rimage +++ b/rimage @@ -1 +1 @@ -Subproject commit 9643a986dda97c6cb339d5c75c0eaa178d8317da +Subproject commit ab0429fdbe563ef6abe499c69b2483e96c4762d0 diff --git a/scripts/cmake/version-build-counter.cmake b/scripts/cmake/version-build-counter.cmake index 4661d2ace34e..c3bcb3b5985b 100644 --- a/scripts/cmake/version-build-counter.cmake +++ b/scripts/cmake/version-build-counter.cmake @@ -8,6 +8,10 @@ set(VERSION_BUILD_COUNTER_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/version-build-cou set(BUILD_COUNTER_PATH "${SOF_ROOT_BINARY_DIRECTORY}/.build") +# Among many other differences, the Zephyr build does not invoke +# sof_add_build_counter_rule() at build time. In other words, Zephyr has +# never supported incrementing the BLD_COUNTERS: SOF_BUILD is always +# equal to the starting value below when building with Zephyr. if(NOT EXISTS "${BUILD_COUNTER_PATH}") file(WRITE "${BUILD_COUNTER_PATH}" "1") endif() diff --git a/scripts/cmake/version.cmake b/scripts/cmake/version.cmake index 6f314ea91348..54e4d0339493 100644 --- a/scripts/cmake/version.cmake +++ b/scripts/cmake/version.cmake @@ -1,13 +1,13 @@ # SPDX-License-Identifier: BSD-3-Clause # Generates header for which version is taken from (in order of precedence): -# 1) .tarball-version file -# 2) git +# 1) .tarball-version file +# 2) sof/versions.json # # Version is checked during configuration step and for every target # that has check_version_h target as dependency -cmake_minimum_required(VERSION 3.13) +cmake_minimum_required(VERSION 3.19) set(VERSION_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/version.cmake) @@ -74,12 +74,20 @@ endif() message(STATUS "GIT_TAG / GIT_LOG_HASH : ${GIT_TAG} / ${GIT_LOG_HASH}") -string(REGEX MATCH "^v([0-9]+)[.]([0-9]+)([.]([0-9]+))?" ignored "${GIT_TAG}") -set(SOF_MAJOR ${CMAKE_MATCH_1}) -set(SOF_MINOR ${CMAKE_MATCH_2}) -set(SOF_MICRO ${CMAKE_MATCH_4}) +file(READ "${SOF_ROOT_SOURCE_DIRECTORY}/versions.json" versions_json) -if(NOT SOF_MICRO MATCHES "^[0-9]+$") +message(VERBOSE "${SOF_ROOT_SOURCE_DIRECTORY}/versions.json=${versions_json}") + +string(JSON SOF_MAJOR GET "${versions_json}" SOF MAJOR) +string(JSON SOF_MINOR GET "${versions_json}" SOF MINOR) +string(JSON SOF_MICRO ERROR_VARIABLE micro_error + GET "${versions_json}" SOF MICRO) + +# Don't confuse "error not found" with "version not found" +if(NOT "${micro_error}" STREQUAL "NOTFOUND") + message(STATUS "versions.json: ${micro_error}, defaulting to 0") + # TODO: default this to .99 on the main, never released branch like zephyr does + # Keep this default SOF_MICRO the same as the one in xtensa-build-zephyr.py set(SOF_MICRO 0) endif() diff --git a/scripts/docker-run.sh b/scripts/docker-run.sh index 29d7ebc0f31a..ee772b8ffc2a 100755 --- a/scripts/docker-run.sh +++ b/scripts/docker-run.sh @@ -33,6 +33,8 @@ test "$(id -u)" = 1000 || >&2 printf "Warning: this script should be run as user ID 1000 to match the container's account\n" set -x +# FIXME: During the transition to sudo-cwd.sh, the tag will be "latest_ubuntu22.04". +# Later it will be back to latest docker run -i -v "${SOF_TOP}":/home/sof/work/sof.git \ -v "${SOF_TOP}":/home/sof/work/sof-bind-mount-DO-NOT-DELETE \ --env CMAKE_BUILD_TYPE \ @@ -42,6 +44,5 @@ docker run -i -v "${SOF_TOP}":/home/sof/work/sof.git \ --env VERBOSE \ --env http_proxy="$http_proxy" \ --env https_proxy="$https_proxy" \ - --user "$(id -u)" \ $SOF_DOCKER_RUN \ - thesofproject/sof "$@" + thesofproject/sof:latest_ubuntu22.04 ./scripts/sudo-cwd.sh "$@" diff --git a/scripts/docker_build/sof_builder/Dockerfile b/scripts/docker_build/sof_builder/Dockerfile index 1647bb9fd0f4..5380d58474f2 100644 --- a/scripts/docker_build/sof_builder/Dockerfile +++ b/scripts/docker_build/sof_builder/Dockerfile @@ -14,8 +14,9 @@ # docker run -it -v :/home/sof/work/sof.git --user `id -u` sof ./incremental.sh # -FROM ubuntu:20.04 -ARG UID=1000 +FROM ubuntu:22.04 +# pick random high value to intentionally mismatch local UID +ARG UID=1999 ARG host_http_proxy ARG host_https_proxy @@ -62,7 +63,11 @@ ARG CLONE_DEFAULTS="--depth 5" # Set up sof user RUN useradd --create-home -d /home/sof -u $UID -G sudo sof && \ + echo 'sof ALL = NOPASSWD: ALL' > /etc/sudoers.d/sof && \ + chmod 0440 /etc/sudoers.d/sof && \ echo "sof:test0000" | chpasswd && adduser sof sudo +# allow others to read/traverse sof home +RUN chmod o+rx /home/sof ENV HOME /home/sof # Use ToT alsa utils for the latest topology patches. @@ -88,7 +93,7 @@ RUN cd "$HOME" && \ git clone $CLONE_DEFAULTS --branch sof-gcc10x $CT_NG_REPO && \ cd crosstool-ng && \ ./bootstrap && ./configure --prefix=`pwd` && make && make install && \ - for arch in imx imx8m imx8ulp rn rmb mt8186 mt8195; do \ + for arch in byt hsw apl cnl imx imx8m imx8ulp rn rmb mt8186 mt8195; do \ echo "$arch: ct-ng build start..." && \ cp config-${arch}-gcc10.2-gdb9 .config && \ # replace the build dist to save space @@ -99,6 +104,10 @@ RUN cd "$HOME" && \ done && \ echo "Stage2: xtensa-overlay, crosstool-ng are done!" +ENV PATH="/home/sof/work/xtensa-byt-elf/bin:${PATH}" +ENV PATH="/home/sof/work/xtensa-hsw-elf/bin:${PATH}" +ENV PATH="/home/sof/work/xtensa-apl-elf/bin:${PATH}" +ENV PATH="/home/sof/work/xtensa-cnl-elf/bin:${PATH}" ENV PATH="/home/sof/work/xtensa-rn-elf/bin:${PATH}" ENV PATH="/home/sof/work/xtensa-rmb-elf/bin:${PATH}" ENV PATH="/home/sof/work/xtensa-imx-elf/bin:${PATH}" @@ -111,7 +120,7 @@ ARG NEWLIB_REPO=https://github.com/jcmvbkbc/newlib-xtensa.git RUN cd "$HOME" && \ git clone $CLONE_DEFAULTS --branch xtensa $NEWLIB_REPO && \ cd newlib-xtensa && \ - for arch in imx imx8m imx8ulp rn rmb mt8186 mt8195; do \ + for arch in byt hsw apl cnl imx imx8m imx8ulp rn rmb mt8186 mt8195; do \ ./configure --target=xtensa-${arch}-elf \ --prefix=/home/sof/work/xtensa-root && \ make && make install && \ diff --git a/scripts/fuzz.sh b/scripts/fuzz.sh index 69fdc90f3ae0..d5fefa98abb5 100755 --- a/scripts/fuzz.sh +++ b/scripts/fuzz.sh @@ -38,11 +38,12 @@ EOFHELP void ipc_cmd(struct ipc_cmd_hdr *_hdr) { -+ __ASSERT(false, "test the fuzzer test"); ++ __ASSERT(false, "test the IPC3 fuzzer test"); + struct sof_ipc_cmd_hdr *hdr = ipc_from_hdr(_hdr); EOF_TEST_PATCH +# When fuzzing IPC4, make the same change in src/ipc/ipc4/handler.c#ipc_cmd() main() { diff --git a/scripts/parse_sparse_output.sh b/scripts/parse_sparse_output.sh index 3b8876e9a060..04d767eeb794 100755 --- a/scripts/parse_sparse_output.sh +++ b/scripts/parse_sparse_output.sh @@ -27,8 +27,12 @@ main() sparse_errors+=(-e '[[:space:]]error:[[:space:]]') + sparse_errors+=(-e '[[:space:]]warning:[[:space:]].*too many warnings') + sparse_errors+=(-e '[[:space:]]warning:[[:space:]].*different address space') + sparse_errors+=(-e '[[:space:]]warning:[[:space:]].*cast removes address space') + ! grep -v 'alsatplg.*topology2.*skip' | grep -i "${sparse_errors[@]}" } diff --git a/scripts/rebuild-testbench.sh b/scripts/rebuild-testbench.sh index b566dc6dcd91..620b15dbeb26 100755 --- a/scripts/rebuild-testbench.sh +++ b/scripts/rebuild-testbench.sh @@ -5,27 +5,44 @@ # fail on any errors set -e +# Defaults +BUILD_TYPE=native +BUILD_DIR_NAME=build_testbench +BUILD_TARGET=install + print_usage() { cat <] + -p Build testbench binary for xt-run for selected platform, e.g. -p tgl -f Build testbench with compiler provided by fuzzer (default path: $HOME/sof/work/AFL/afl-gcc) + -j number of parallel make/ninja jobs. Defaults to /usr/bin/nproc. + You MUST re-run with -j1 when something is failing! EOFUSAGE } +# die is copy from xtensa-build-all.sh +die() +{ + >&2 printf '%s ERROR: ' "$0" + # We want die() to be usable exactly like printf + # shellcheck disable=SC2059 + >&2 printf "$@" + exit 1 +} + rebuild_testbench() { cd "$BUILD_TESTBENCH_DIR" - rm -rf build_testbench - - mkdir build_testbench - cd build_testbench + rm -rf "$BUILD_DIR_NAME" + mkdir "$BUILD_DIR_NAME" + cd "$BUILD_DIR_NAME" cmake -DCMAKE_INSTALL_PREFIX=install .. - cmake --build . -- -j"$(nproc)" install + cmake --build . -- -j"${jobs}" $BUILD_TARGET } export_CC_with_afl() @@ -34,6 +51,72 @@ export_CC_with_afl() export CC=${SOF_AFL} } +setup_xtensa_tools_build() +{ + BUILD_TYPE=xt + BUILD_TARGET= + BUILD_DIR_NAME=build_xt_testbench + + # check needed environment variables + test -n "${XTENSA_TOOLS_ROOT}" || die "XTENSA_TOOLS_ROOT need to be set.\n" + + # Get compiler version for platform + + # 'shellcheck -x ...' works only from the top directory + # shellcheck source=scripts/set_xtensa_params.sh + source "$SCRIPT_DIR/set_xtensa_params.sh" "$BUILD_PLATFORM" + + test -n "${XTENSA_TOOLS_VERSION}" || + die "Illegal platform $BUILD_PLATFORM, no XTENSA_TOOLS_VERSION found.\n" + test -n "${XTENSA_CORE}" || + die "Illegal platform $BUILD_PLATFORM, no XTENSA_CORE found.\n" + + compiler="xt-xcc" + install_bin=install/tools/$XTENSA_TOOLS_VERSION/XtensaTools/bin + tools_bin=$XTENSA_TOOLS_ROOT/$install_bin + testbench_sections="-Wl,--sections-placement $BUILD_TESTBENCH_DIR/testbench_xcc_sections.txt" + export CC=$tools_bin/$compiler + export LD=$tools_bin/xt-ld + export OBJDUMP=$tools_bin/xt-objdump + export LDFLAGS="-mlsp=sim -Wl,-LE $testbench_sections" + export XTENSA_CORE +} + +export_xtensa_setup() +{ + export_dir=$BUILD_TESTBENCH_DIR/$BUILD_DIR_NAME + export_script=$export_dir/xtrun_env.sh + xtbench=$export_dir/testbench + xtbench_run="XTENSA_CORE=$XTENSA_CORE \$XTENSA_TOOLS_ROOT/$install_bin/xt-run $xtbench" + cat < "$export_script" +export XTENSA_TOOLS_ROOT=$XTENSA_TOOLS_ROOT +export XTENSA_CORE=$XTENSA_CORE +XTENSA_PATH=$tools_bin +EOFSETUP +} + +testbench_usage() +{ + case "$BUILD_TYPE" in + xt) + export_xtensa_setup + cat <&2 printf 'testbench_usage: unknown/missing BUILD_TYPE=%s\n' "$BUILD_TYPE" ;; + esac +} + main() { SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) @@ -41,15 +124,23 @@ main() BUILD_TESTBENCH_DIR="$SOF_REPO"/tools/testbench : "${SOF_AFL:=$HOME/sof/work/AFL/afl-gcc}" - while getopts "fh" OPTION; do - case "$OPTION" in - f) export_CC_with_afl;; - h) print_usage; exit 1;; - *) print_usage; exit 1;; - esac + jobs=$(nproc) + while getopts "fhj:p:" OPTION; do + case "$OPTION" in + p) + BUILD_PLATFORM="$OPTARG" + setup_xtensa_tools_build + ;; + f) export_CC_with_afl;; + j) jobs=$(printf '%d' "$OPTARG") ;; + h) print_usage; exit 1;; + *) print_usage; exit 1;; + esac done rebuild_testbench + + testbench_usage } main "$@" diff --git a/scripts/set_xtensa_params.sh b/scripts/set_xtensa_params.sh new file mode 100644 index 000000000000..1dbd7018c0d2 --- /dev/null +++ b/scripts/set_xtensa_params.sh @@ -0,0 +1,84 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2023 Intel Corporation. All rights reserved. + +# Sourced script argument is a non-standard bash extension +platform=$1 + +# Note: This duplicates xtensa-build-zephyr.py + +case "$platform" in + tgl) + PLATFORM="tgplp" + XTENSA_CORE="cavs2x_LX6HiFi3_2017_8" + HOST="xtensa-cnl-elf" + XTENSA_TOOLS_VERSION="RG-2017.8-linux" + HAVE_ROM='yes' + IPC4_CONFIG_OVERLAY="tigerlake_ipc4" + # default key for TGL + PLATFORM_PRIVATE_KEY="-D${SIGNING_TOOL}_PRIVATE_KEY=$SOF_TOP/keys/otc_private_key_3k.pem" + ;; + tgl-h) + PLATFORM="tgph" + XTENSA_CORE="cavs2x_LX6HiFi3_2017_8" + HOST="xtensa-cnl-elf" + XTENSA_TOOLS_VERSION="RG-2017.8-linux" + HAVE_ROM='yes' + # default key for TGL + PLATFORM_PRIVATE_KEY="-D${SIGNING_TOOL}_PRIVATE_KEY=$SOF_TOP/keys/otc_private_key_3k.pem" + ;; + imx8) + PLATFORM="imx8" + XTENSA_CORE="hifi4_nxp_v3_3_1_2_2017" + HOST="xtensa-imx-elf" + XTENSA_TOOLS_VERSION="RG-2017.8-linux" + ;; + imx8x) + PLATFORM="imx8x" + XTENSA_CORE="hifi4_nxp_v3_3_1_2_2017" + HOST="xtensa-imx-elf" + XTENSA_TOOLS_VERSION="RG-2017.8-linux" + ;; + imx8m) + PLATFORM="imx8m" + XTENSA_CORE="hifi4_mscale_v0_0_2_2017" + HOST="xtensa-imx8m-elf" + XTENSA_TOOLS_VERSION="RG-2017.8-linux" + ;; + imx8ulp) + PLATFORM="imx8ulp" + XTENSA_CORE="hifi4_nxp2_ulp_prod" + HOST="xtensa-imx8ulp-elf" + XTENSA_TOOLS_VERSION="RG-2017.8-linux" + ;; + rn) + PLATFORM="renoir" + XTENSA_CORE="ACP_3_1_001_PROD_2019_1" + HOST="xtensa-rn-elf" + XTENSA_TOOLS_VERSION="RI-2019.1-linux" + ;; + rmb) + PLATFORM="rembrandt" + ARCH="xtensa" + XTENSA_CORE="LX7_HiFi5_PROD" + HOST="xtensa-rmb-elf" + XTENSA_TOOLS_VERSION="RI-2019.1-linux" + ;; + mt8186) + PLATFORM="mt8186" + XTENSA_CORE="hifi5_7stg_I64D128" + HOST="xtensa-mt8186-elf" + XTENSA_TOOLS_VERSION="RI-2020.5-linux" + ;; + mt8188) + PLATFORM="mt8188" + XTENSA_CORE="hifi5_7stg_I64D128" + HOST="xtensa-mt8188-elf" + XTENSA_TOOLS_VERSION="RI-2020.5-linux" + ;; + mt8195) + PLATFORM="mt8195" + XTENSA_CORE="hifi4_8195_PROD" + HOST="xtensa-mt8195-elf" + XTENSA_TOOLS_VERSION="RI-2019.1-linux" + ;; +esac diff --git a/scripts/test-repro-build.sh b/scripts/test-repro-build.sh index 3ea0c63c96d5..d06c920c628d 100755 --- a/scripts/test-repro-build.sh +++ b/scripts/test-repro-build.sh @@ -39,7 +39,7 @@ SOF2="$SOF_PARENT"/sof-bind-mount-DO-NOT-DELETE # considerably, replace "sof" with something of the same length: # SOF2="$SOF_PARENT"/sog -PLATFS=(tgl) +PLATFS=(imx8) # diffoscope is great but it has hundreds of dependencies, too long to # install for CI so we don't use it here. This is just an alias diff --git a/scripts/xtensa-build-all.sh b/scripts/xtensa-build-all.sh index 05cb8f13dc98..059cd07fb283 100755 --- a/scripts/xtensa-build-all.sh +++ b/scripts/xtensa-build-all.sh @@ -8,7 +8,6 @@ set -e # Platforms built and tested by default in CI using the `-a` option. # They must have a toolchain available in the latest Docker image. DEFAULT_PLATFORMS=( - tgl tgl-h imx8 imx8x imx8m imx8ulp rn rmb mt8186 mt8195 @@ -199,25 +198,6 @@ do PLATFORM_PRIVATE_KEY='' case $platform in - tgl) - PLATFORM="tgplp" - XTENSA_CORE="cavs2x_LX6HiFi3_2017_8" - HOST="xtensa-cnl-elf" - XTENSA_TOOLS_VERSION="RG-2017.8-linux" - HAVE_ROM='yes' - IPC4_CONFIG_OVERLAY="tigerlake_ipc4" - # default key for TGL - PLATFORM_PRIVATE_KEY="-D${SIGNING_TOOL}_PRIVATE_KEY=$SOF_TOP/keys/otc_private_key_3k.pem" - ;; - tgl-h) - PLATFORM="tgph" - XTENSA_CORE="cavs2x_LX6HiFi3_2017_8" - HOST="xtensa-cnl-elf" - XTENSA_TOOLS_VERSION="RG-2017.8-linux" - HAVE_ROM='yes' - # default key for TGL - PLATFORM_PRIVATE_KEY="-D${SIGNING_TOOL}_PRIVATE_KEY=$SOF_TOP/keys/otc_private_key_3k.pem" - ;; imx8) PLATFORM="imx8" XTENSA_CORE="hifi4_nxp_v3_3_1_2_2017" diff --git a/scripts/xtensa-build-zephyr.py b/scripts/xtensa-build-zephyr.py index 0467bf4feaa2..8b70d63bf8e7 100755 --- a/scripts/xtensa-build-zephyr.py +++ b/scripts/xtensa-build-zephyr.py @@ -35,6 +35,7 @@ import warnings import fnmatch import hashlib +import json import gzip import dataclasses import concurrent.futures as concurrent @@ -60,7 +61,6 @@ default_rimage_key = pathlib.Path(SOF_TOP, "keys", "otc_private_key.pem") sof_fw_version = None -sof_build_version = None if py_platform.system() == "Windows": xtensa_tools_version_postfix = "-win32" @@ -104,20 +104,29 @@ class PlatformConfig: f"RI-2022.10{xtensa_tools_version_postfix}", "ace10_LX7HiFi4_2022_10", ), + "lnl" : PlatformConfig( + "lnl", "intel_adsp_ace20_lnl", + f"RI-2022.10{xtensa_tools_version_postfix}", + "ace10_LX7HiFi4_2022_10", + ), + # NXP platforms "imx8" : PlatformConfig( "imx8", "nxp_adsp_imx8", - None, None, + f"RI-2023.11{xtensa_tools_version_postfix}", + "hifi4_nxp_v5_3_1_prod", RIMAGE_KEY = "key param ignored by imx8", ), "imx8x" : PlatformConfig( "imx8x", "nxp_adsp_imx8x", - None, None, + f"RI-2023.11{xtensa_tools_version_postfix}", + "hifi4_nxp_v5_3_1_prod", RIMAGE_KEY = "key param ignored by imx8x" ), "imx8m" : PlatformConfig( "imx8m", "nxp_adsp_imx8m", - None, None, + f"RI-2023.11{xtensa_tools_version_postfix}", + "hifi4_mscale_v2_0_2_prod", RIMAGE_KEY = "key param ignored by imx8m" ), } @@ -161,7 +170,7 @@ def parse_args(): parser.add_argument("platforms", nargs="*", action=validate_platforms_arguments, help="List of platforms to build") parser.add_argument("-d", "--debug", required=False, action="store_true", - help="Enable debug build") + help="Shortcut for: -o sof/app/debug_overlay.conf") parser.add_argument("-i", "--ipc", required=False, choices=["IPC4"], help="""Applies --overlay /ipc4_overlay.conf and a different rimage config. Valid only for IPC3 platforms supporting IPC4 too.""") @@ -273,14 +282,15 @@ def execute_command(*run_args, **run_kwargs): output = f"{print_cwd}; running command:\n {print_args}" env_arg = run_kwargs.get('env') env_change = set(env_arg.items()) - set(os.environ.items()) if env_arg else None - if env_change: - output += "\n... with extra/modified environment:" + if env_change and (run_kwargs.get('sof_log_env') or args.verbose >= 1): + output += "\n... with extra/modified environment:\n" for k_v in env_change: - output += f"\n{k_v[0]}={k_v[1]}" + output += f"{k_v[0]}={k_v[1]}\n" print(output, flush=True) + run_kwargs = {k: run_kwargs[k] for k in run_kwargs if not k.startswith("sof_")} - if run_kwargs.get('check') is None: + if not 'check' in run_kwargs: run_kwargs['check'] = True #pylint:disable=subprocess-run-check @@ -440,30 +450,26 @@ def west_update(): execute_command(["west", "update"], check=True, timeout=3000, cwd=west_top) -def get_build_and_sof_version(abs_build_dir): - """[summary] Get version string major.minor.micro and build of SOF +def get_sof_version(): + """[summary] Get version string major.minor.micro of SOF firmware file. When building multiple platforms from the same SOF commit, all platforms share the same version. So for the 1st platform, - generate the version string from sof_version.h and later platforms will + extract the version information from sof/versions.json and later platforms will reuse it. """ global sof_fw_version - global sof_build_version - if sof_fw_version and sof_build_version: - return sof_fw_version, sof_build_version + if sof_fw_version: + return sof_fw_version versions = {} - with open(pathlib.Path(abs_build_dir, - "zephyr/include/generated/sof_versions.h"), encoding="utf8") as hfile: - for hline in hfile: - words = hline.split() - if words[0] == '#define': - versions[words[1]] = words[2] - sof_fw_version = versions['SOF_MAJOR'] + '.' + versions['SOF_MINOR'] + '.' + \ - versions['SOF_MICRO'] - sof_build_version = versions['SOF_BUILD'] - - return sof_fw_version, sof_build_version + with open(SOF_TOP / "versions.json") as versions_file: + versions = json.load(versions_file) + # Keep this default value the same as the default SOF_MICRO in version.cmake + sof_micro = versions['SOF'].get('MICRO', "0") + sof_fw_version = ( + f"{versions['SOF']['MAJOR']}.{versions['SOF']['MINOR']}.{sof_micro}" + ) + return sof_fw_version def rmtree_if_exists(directory): "This is different from ignore_errors=False because it deletes everything or nothing" @@ -520,6 +526,60 @@ def build_rimage(): execute_command(rimage_build_cmd, cwd=west_top) +def rimage_configuration(platform_dict): + + sign_cmd = [] + + rimage_executable = shutil.which("rimage", path=RIMAGE_BUILD_DIR) + + sign_cmd += ["--tool-path", rimage_executable, "--"] + + # Flatten the list of [ ( "-o", "value" ), ...] tuples + for t in rimage_options(platform_dict): + sign_cmd += t + + return sign_cmd + + +def rimage_options(platform_dict): + """Return a list of default rimage options as a list of tuples, + example: [ (-f, 2.5.0), (-b, 1), (-k, key.pem),... ] + + """ + opts = [] + + signing_key = "" + if args.key: + signing_key = args.key + elif "RIMAGE_KEY" in platform_dict: + signing_key = platform_dict["RIMAGE_KEY"] + else: + signing_key = default_rimage_key + + opts.append(("-k", str(signing_key))) + + sof_fw_vers = get_sof_version() + + opts.append(("-f", sof_fw_vers)) + + # Default value is 0 in rimage but for Zephyr the "build counter" has always + # been hardcoded to 1 in CMake and there is even a (broken) test that fails + # when it's not hardcoded to 1. + # FIXME: drop this line once the following test is fixed + # tests/avs/fw_00_basic/test_01_load_fw_extended.py::TestLoadFwExtended::():: + # test_00_01_load_fw_and_check_version + opts.append(("-b", "1")) + + if args.ipc == "IPC4": + rimage_desc = platform_dict["IPC4_RIMAGE_DESC"] + else: + rimage_desc = platform_dict["name"] + ".toml" + + opts.append(("-c", str(RIMAGE_SOURCE_DIR / "config" / rimage_desc))) + + return opts + + STAGING_DIR = None def build_platforms(): global west_top, SOF_TOP @@ -587,16 +647,6 @@ def build_platforms(): platform_build_dir_name = f"build-{platform}" - # https://docs.zephyrproject.org/latest/guides/west/build-flash-debug.html#one-time-cmake-arguments - # https://github.com/zephyrproject-rtos/zephyr/pull/40431#issuecomment-975992951 - abs_build_dir = pathlib.Path(west_top, platform_build_dir_name) - if (pathlib.Path(abs_build_dir, "build.ninja").is_file() - or pathlib.Path(abs_build_dir, "Makefile").is_file()): - if args.cmake_args and not args.pristine: - print(args.cmake_args) - raise RuntimeError("Some CMake arguments are ignored in incremental builds, " - + f"you must delete {abs_build_dir} first") - PLAT_CONFIG = platform_dict["PLAT_CONFIG"] build_cmd = ["west"] build_cmd += ["-v"] * args.verbose @@ -630,9 +680,30 @@ def build_platforms(): overlays = ";".join(overlays) build_cmd.append(f"-DOVERLAY_CONFIG={overlays}") + abs_build_dir = pathlib.Path(west_top, platform_build_dir_name) + + # Longer story in https://github.com/zephyrproject-rtos/zephyr/pull/56671 + if not args.pristine and ( + pathlib.Path(abs_build_dir, "build.ninja").is_file() + or pathlib.Path(abs_build_dir, "Makefile").is_file() + ): + if args.cmake_args or overlays: + warnings.warn("""CMake args slow down incremental builds. + Passing CMake parameters and overlays on the command line slows down incremental builds + see https://docs.zephyrproject.org/latest/guides/west/build-flash-debug.html#one-time-cmake-arguments + Try "west config build.cmake-args -- ..." instead.""") + + sign_cmd = ["west"] + sign_cmd += ["-v"] * args.verbose + sign_cmd += ["sign", "--build-dir", platform_build_dir_name, "--tool", "rimage"] + sign_cmd += rimage_configuration(platform_dict) + + # Make sure the build logs don't leave anything hidden + execute_command(['west', 'config', '-l'], cwd=west_top) + # Build try: - execute_command(build_cmd, cwd=west_top, env=platf_build_environ) + execute_command(build_cmd, cwd=west_top, env=platf_build_environ, sof_log_env=True) except subprocess.CalledProcessError as cpe: zephyr_path = pathlib.Path(west_top, "zephyr") if not os.path.exists(zephyr_path): @@ -648,32 +719,6 @@ def build_platforms(): execute_command([str(smex_executable), "-l", str(fw_ldc_file), str(input_elf_file)]) # Sign firmware - rimage_executable = shutil.which("rimage", path=RIMAGE_BUILD_DIR) - rimage_config = RIMAGE_SOURCE_DIR / "config" - sign_cmd = ["west"] - sign_cmd += ["-v"] * args.verbose - sign_cmd += ["sign", "--build-dir", platform_build_dir_name, "--tool", "rimage"] - sign_cmd += ["--tool-path", rimage_executable] - signing_key = "" - if args.key: - signing_key = args.key - elif "RIMAGE_KEY" in platform_dict: - signing_key = platform_dict["RIMAGE_KEY"] - else: - signing_key = default_rimage_key - - sign_cmd += ["--tool-data", str(rimage_config), "--", "-k", str(signing_key)] - - sof_fw_vers, sof_build_vers = get_build_and_sof_version(abs_build_dir) - - sign_cmd += ["-f", sof_fw_vers] - - sign_cmd += ["-b", sof_build_vers] - - if args.ipc == "IPC4": - rimage_desc = pathlib.Path(SOF_TOP, "rimage", "config", platform_dict["IPC4_RIMAGE_DESC"]) - sign_cmd += ["-c", str(rimage_desc)] - execute_command(sign_cmd, cwd=west_top) if platform not in RI_INFO_UNSUPPORTED: @@ -726,16 +771,13 @@ def install_platform(platform, sof_platform_output_dir, platf_build_environ): # Regular name output_fwname = "".join(["sof-", platform, ".ri"]) - shutil.copy2(abs_build_dir / "zephyr.ri", abs_build_dir / output_fwname) - fw_file_to_copy = abs_build_dir / output_fwname - install_key_dir = sof_platform_output_dir if args.key_type_subdir != "none": install_key_dir = install_key_dir / args.key_type_subdir os.makedirs(install_key_dir, exist_ok=True) # looses file owner and group - file is commonly accessible - shutil.copy2(fw_file_to_copy, install_key_dir) + shutil.copy2(abs_build_dir / "zephyr.ri", install_key_dir / output_fwname) # sof-info/ directory @@ -864,7 +906,7 @@ def gzip_compress(fname, gzdst=None): RI_INFO_UNSUPPORTED += ['mt8186', 'mt8195'] # sof_ri_info.py has not caught up with the latest rimage yet: these will print a warning. -RI_INFO_FIXME = ['mtl'] +RI_INFO_FIXME = ['mtl', 'lnl'] def reproducible_checksum(platform, ri_file): diff --git a/smex/CMakeLists.txt b/smex/CMakeLists.txt index fbad0a9519ba..5d198832f472 100644 --- a/smex/CMakeLists.txt +++ b/smex/CMakeLists.txt @@ -19,7 +19,11 @@ add_executable(smex # In addition to the usual flags from CMAKE_BUILD_TYPE target_compile_options(smex PRIVATE - -Wall -Werror -Wl,-EL -Wmissing-prototypes -Wimplicit-fallthrough=3 + -Wall -Werror -Wmissing-prototypes -Wimplicit-fallthrough +) + +target_link_options(smex PRIVATE + -Wall -Werror -Wl,-EL ) target_include_directories(smex PRIVATE diff --git a/src/arch/xtensa/CMakeLists.txt b/src/arch/xtensa/CMakeLists.txt index 4a5fe01567c5..c51dd956491b 100644 --- a/src/arch/xtensa/CMakeLists.txt +++ b/src/arch/xtensa/CMakeLists.txt @@ -20,20 +20,10 @@ elseif(CONFIG_MT8195) set(platform_folder mt8195) endif() -if(CONFIG_CAVS) - set(family_path intel/cavs) -endif() - set(fw_name ${CONFIG_RIMAGE_SIGNING_SCHEMA}) -if(CONFIG_XT_BOOT_LOADER) - set(build_bootloader y) - set(build_module y) -endif() - set(platform_ld_script ${platform_folder}.x) set(platform_rom_ld_script rom.x) -set(platform_bootldr_ld_script boot_ldr.x) if(CONFIG_RENOIR) set(platform_folder amd/renoir) @@ -229,11 +219,7 @@ if(CONFIG_XT_INTERRUPT_LEVEL_5) target_link_libraries(sof_static_libraries INTERFACE xlevel5) endif() -if(build_bootloader) - add_local_sources(sof main-entry.S) -else() - target_link_libraries(sof_static_libraries INTERFACE reset) -endif() +target_link_libraries(sof_static_libraries INTERFACE reset) target_link_libraries(sof_ld_flags INTERFACE "-Wl,-Map=sof.map") target_link_libraries(sof_ld_flags INTERFACE "-T${PROJECT_BINARY_DIR}/${platform_ld_script}") @@ -255,66 +241,11 @@ add_custom_target(sof_post_process # contains extra output that should be generated for bin target add_custom_target(bin_extras) -# bootloader binary - -if(build_bootloader) - add_executable(bootloader "") - - add_dependencies(bootloader rimage_ep) - # This line should be next to the boot_module - # (resp. base_module) definitions but there are too many of - # them; one per platform. So do it only once here instead. - add_dependencies(boot_module rimage_ep) - add_dependencies(base_module rimage_ep) - - target_include_directories(bootloader PRIVATE ${PROJECT_SOURCE_DIR}/rimage/src/include) - target_include_directories(boot_module PRIVATE ${PROJECT_SOURCE_DIR}/rimage/src/include) - target_include_directories(base_module PRIVATE ${PROJECT_SOURCE_DIR}/rimage/src/include) - - - target_link_libraries(bootloader PRIVATE sof_options) - add_local_sources(bootloader xtos/_vectors.S ${PROJECT_SOURCE_DIR}/src/platform/${family_path}/boot_entry.S ${PROJECT_SOURCE_DIR}/src/platform/${family_path}/boot_loader.c) - target_link_libraries(bootloader PRIVATE reset) - target_link_libraries(bootloader PRIVATE hal) - target_link_libraries(bootloader PRIVATE "-T${PROJECT_BINARY_DIR}/${platform_bootldr_ld_script}") - sof_add_ld_script(bootloader ${platform_bootldr_ld_script}) - sof_append_relative_path_definitions(bootloader) - - add_custom_target( - bootloader_dump - COMMAND ${CMAKE_COMMAND} -E copy bootloader bootloader-${fw_name} - COMMAND ${CMAKE_OBJCOPY} -O binary -j .data ${PROJECT_BINARY_DIR}/src/platform/${platform_folder}/boot_module mod-boot-${fw_name}.bin - COMMAND ${CMAKE_OBJCOPY} --add-section .module=mod-boot-${fw_name}.bin --set-section-flags .module=load,readonly bootloader-${fw_name} - COMMAND ${CMAKE_OBJCOPY} -O binary bootloader bootloader-${fw_name}.bin - COMMAND ${CMAKE_OBJDUMP} -h -D bootloader > bootloader-${fw_name}.lmap - COMMAND ${CMAKE_OBJDUMP} -S bootloader > bootloader-${fw_name}.lst - COMMAND ${CMAKE_OBJDUMP} -D bootloader > bootloader-${fw_name}.dis - DEPENDS bootloader boot_module - VERBATIM - USES_TERMINAL - ) - - set(bootloader_binary_path bootloader-${fw_name}) - - # Add 'base_module' section to sof ELF - add_custom_target( - process_base_module - COMMAND ${CMAKE_OBJCOPY} -O binary -j .data ${PROJECT_BINARY_DIR}/src/platform/${platform_folder}/base_module mod-${fw_name}.bin - COMMAND ${CMAKE_OBJCOPY} --add-section .module=mod-${fw_name}.bin --set-section-flags .module=load,readonly sof-pre sof-${fw_name} - DEPENDS prepare_sof_post_process base_module bootloader_dump - VERBATIM - USES_TERMINAL - ) - -else() - set(bootloader_binary_path) - - # Do nothing / pass-through - add_custom_target(process_base_module - COMMAND ${CMAKE_COMMAND} -E copy sof-pre sof-${fw_name} - DEPENDS prepare_sof_post_process - ) -endif() +# Do nothing / pass-through +add_custom_target(process_base_module + COMMAND ${CMAKE_COMMAND} -E copy sof-pre sof-${fw_name} + DEPENDS prepare_sof_post_process +) if(CONFIG_BUILD_VM_ROM) add_executable(rom "") @@ -455,7 +386,6 @@ if(MEU_PATH OR DEFINED MEU_NO_SIGN) # Don't sign with rimage -f ${SOF_MAJOR}.${SOF_MINOR}.${SOF_MICRO} -b ${SOF_BUILD} -e - ${bootloader_binary_path} sof-${fw_name} DEPENDS sof_post_process rimage_ep VERBATIM @@ -496,7 +426,6 @@ else() # sign with rimage -f ${SOF_MAJOR}.${SOF_MINOR}.${SOF_MICRO} -b ${SOF_BUILD} -e - ${bootloader_binary_path} sof-${fw_name} DEPENDS sof_post_process rimage_ep VERBATIM diff --git a/src/arch/xtensa/hal/atomics.c b/src/arch/xtensa/hal/atomics.c index 01a2c9f6508b..d7abc128f966 100644 --- a/src/arch/xtensa/hal/atomics.c +++ b/src/arch/xtensa/hal/atomics.c @@ -3,9 +3,9 @@ #include #include -int _xt_atomic_compare_exchange_4(int32_t *address, int32_t test_value, int32_t set_value); +int _xt_atomic_compare_exchange_4(int *address, int32_t test_value, int32_t set_value); -int _xt_atomic_compare_exchange_4(int32_t *address, int32_t test_value, int32_t set_value) +int _xt_atomic_compare_exchange_4(int *address, int32_t test_value, int32_t set_value) { return xthal_compare_and_set(address, test_value, set_value); } diff --git a/src/arch/xtensa/include/xtensa/config/core.h b/src/arch/xtensa/include/xtensa/config/core.h index f5bb44faf2ab..4cf7606df707 100644 --- a/src/arch/xtensa/include/xtensa/config/core.h +++ b/src/arch/xtensa/include/xtensa/config/core.h @@ -36,6 +36,24 @@ #ifndef XTENSA_CONFIG_CORE_H #define XTENSA_CONFIG_CORE_H +/* + * This define is used by the new 2023 xt-clang toolchain and, while there are a few definitions + * (identical to this one) in various implementations such as newlib, none of them is in use when + * building SOF with Zephyr and XtensaTools. + */ + +#if defined(__ZEPHYR__) + +#ifndef __UINT32_C +#define __UINT32_C(x) x ## U +#endif + +#ifndef UINT32_C +#define UINT32_C(x) __UINT32_C(x) +#endif + +#endif + /* CONFIGURATION INDEPENDENT DEFINITIONS: */ #ifdef __XTENSA__ #include diff --git a/src/arch/xtensa/xtos/crt1-boards-rom.S b/src/arch/xtensa/xtos/crt1-boards-rom.S deleted file mode 100644 index e5391999981c..000000000000 --- a/src/arch/xtensa/xtos/crt1-boards-rom.S +++ /dev/null @@ -1,166 +0,0 @@ -// crt1-boards.S -// -// For most hardware / boards, this code sets up the C calling context -// (setting up stack, PS, and clearing BSS) and jumps to __clibrary_start -// which sets up the C library, calls constructors and registers destructors, -// and calls main(). -// -// Control arrives here at _start from the reset vector or from crt0-app.S. - -// Copyright (c) 1998-2017 Cadence Design Systems, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -#include - -#include - -// Exports -.global _start - -// Imports -// __clibrary_init from C library (eg. newlib or uclibc) -// exit from C library -// main from user application -// board_init board-specific (uart/mingloss/tinygloss.c) -// xthal_dcache_all_writeback from HAL library -// __stack from linker script (see LSP Ref Manual) -// _bss_table_start from linker script (see LSP Ref Manual) -// _bss_table_end from linker script (see LSP Ref Manual) - -.type main, @function - -// Macros to abstract away ABI differences - -#if __XTENSA_CALL0_ABI__ -# define CALL call0 -# define CALLX callx0 -#else -# define CALL call4 -# define CALLX callx4 -#endif - -/**************************************************************************/ - - .text - .align 4 - .literal_position - -// VM ROM jumps to boot loader in IMR/SRAM -_boot_ldr_entry: - .word IMR_BOOT_LDR_TEXT_ENTRY_BASE - .align 4 - -_start: - // _start is typically NOT at the beginning of the text segment -- - // it is always called from either the reset vector or other code - // that does equivalent initialization (such as crt0-app.S). - // - // Assumptions on entry to _start: - // - low (level-one) and medium priority interrupts are disabled - // via PS.INTLEVEL and/or INTENABLE (PS.INTLEVEL is expected to - // be zeroed, to potentially enable them, before calling main) - // - C calling context not initialized: - // - PS not initialized - // - SP not initialized - // - the following are initialized: - // - LITBASE, cache attributes, WindowBase, WindowStart, - // CPENABLE, FP's FCR and FSR, EXCSAVE[n] - - // Keep a0 zero. It is used to initialize a few things. - // It is also the return address, where zero indicates - // that the frame used by _start is the bottommost frame. - // -#if !XCHAL_HAVE_HALT || !XCHAL_HAVE_BOOTLOADER // not needed for Xtensa TX - movi a0, 0 // keep this register zero. -#endif - -#if XTOS_RESET_UNNEEDED && !XCHAL_HAVE_HALT -#include "reset-unneeded.S" -#endif - -#if CONFIG_XT_BOOT_LOADER - .weak _Level2FromVector - .weak _Level3FromVector - .weak _Level4FromVector - .weak _Level5FromVector - - movi a4, _Level2FromVector - writesr excsave 2 a4 - movi a4, _Level3FromVector - writesr excsave 3 a4 - movi a4, _Level4FromVector - writesr excsave 4 a4 - movi a4, _Level5FromVector - writesr excsave 5 a4 -#endif - - // Assign stack ptr before PS is initialized to avoid any debugger - // side effects and prevent from double exception. - movi sp, __stack - - /* - * Now that sp (a1) is set, we can set PS as per the application - * (user vector mode, enable interrupts, enable window exceptions if applicable). - */ -#if XCHAL_HAVE_EXCEPTIONS - movi a3, PS_UM|PS_WOE_ABI // PS.WOE = 0|1, PS.UM = 1, PS.EXCM = 0, PS.INTLEVEL = 0 - wsr.ps a3 - rsync -#endif - - /* - * Do any initialization that affects the memory map, such as - * setting up TLB entries, that needs to be done before we can - * successfully clear BSS (e.g. if some BSS segments are in - * remapped areas). - * - * NOTE: This hook works where the reset vector does not unpack - * segments (see "ROM packing" in the LSP manual), or where - * unpacking of segments is not affected by memory remapping. - * If ROM unpacking is affected, TLB setup must be done in - * assembler from the reset vector. - * - * The __memmap_init() routine can be a C function, however it - * does not have BSS initialized! In particular, __memmap_init() - * cannot set BSS variables, i.e. uninitialized global variables - * (they'll be wiped out by the following BSS clear), nor can it - * assume they are yet initialized to zero. - * - * The __memmap_init() function is optional. It is marked as a - * weak symbol, so that it gets valued zero if not defined. - */ - .weak __memmap_init - movi a4, __memmap_init - beqz a4, 1f - CALLX a4 -1: - l32r a0, _boot_ldr_entry // load SRAM reset handler address - callx12 a0 // jump to the handler - -dead: nop - j dead - - .data - // Mark argc/argv/envp parameters as weak so that an external - // object file can override them. - .text - - .size _start, . - _start diff --git a/src/audio/CMakeLists.txt b/src/audio/CMakeLists.txt index 82e11205e34b..90168d890522 100644 --- a/src/audio/CMakeLists.txt +++ b/src/audio/CMakeLists.txt @@ -58,11 +58,6 @@ if((NOT CONFIG_LIBRARY) OR CONFIG_LIBRARY_STATIC) switch.c ) endif() - if(CONFIG_IPC4_GATEWAY) - add_local_sources(sof - ipcgtw.c - ) - endif() if(CONFIG_COMP_DAI) add_local_sources(sof dai-legacy.c diff --git a/src/audio/aria/aria.c b/src/audio/aria/aria.c index e2789598463b..d258fbc13d5c 100644 --- a/src/audio/aria/aria.c +++ b/src/audio/aria/aria.c @@ -218,16 +218,20 @@ static void aria_free(struct comp_dev *dev) static void aria_set_stream_params(struct comp_buffer *buffer, struct aria_data *cd) { struct comp_buffer __sparse_cache *buffer_c; + enum sof_ipc_frame valid_fmt, frame_fmt; buffer_c = buffer_acquire(buffer); - buffer_c->stream.channels = cd->chan_cnt; - buffer_c->stream.rate = cd->base.audio_fmt.sampling_frequency; buffer_c->buffer_fmt = cd->base.audio_fmt.interleaving_style; audio_stream_fmt_conversion(cd->base.audio_fmt.depth, cd->base.audio_fmt.valid_bit_depth, - &buffer_c->stream.frame_fmt, - &buffer_c->stream.valid_sample_fmt, + &frame_fmt, &valid_fmt, cd->base.audio_fmt.s_type); + + audio_stream_set_frm_fmt(&buffer_c->stream, frame_fmt); + audio_stream_set_valid_fmt(&buffer_c->stream, valid_fmt); + audio_stream_set_channels(&buffer_c->stream, cd->chan_cnt); + audio_stream_set_rate(&buffer_c->stream, cd->base.audio_fmt.sampling_frequency); + buffer_release(buffer_c); } @@ -326,7 +330,7 @@ static int aria_copy(struct comp_dev *dev) buffer_stream_invalidate(source_c, source_bytes); for (i = 0; i < c.frames; i++) { - for (channel = 0; channel < sink_c->stream.channels; channel++) { + for (channel = 0; channel < audio_stream_get_channels(&sink_c->stream); channel++) { cd->buf_in[frag] = *(int32_t *)audio_stream_read_frag_s32(&source_c->stream, frag); @@ -334,16 +338,18 @@ static int aria_copy(struct comp_dev *dev) } } dcache_writeback_region((__sparse_force void __sparse_cache *)cd->buf_in, - c.frames * sink_c->stream.channels * sizeof(int32_t)); + c.frames * audio_stream_get_channels(&sink_c->stream) * + sizeof(int32_t)); aria_process_data(dev, cd->buf_out, sink_bytes / sizeof(uint32_t), cd->buf_in, source_bytes / sizeof(uint32_t)); dcache_writeback_region((__sparse_force void __sparse_cache *)cd->buf_out, - c.frames * sink_c->stream.channels * sizeof(int32_t)); + c.frames * audio_stream_get_channels(&sink_c->stream) * + sizeof(int32_t)); frag = 0; for (i = 0; i < c.frames; i++) { - for (channel = 0; channel < sink_c->stream.channels; channel++) { + for (channel = 0; channel < audio_stream_get_channels(&sink_c->stream); channel++) { destp = audio_stream_write_frag_s32(&sink_c->stream, frag); *destp = cd->buf_out[frag]; diff --git a/src/audio/asrc/asrc.c b/src/audio/asrc/asrc.c index d98d86745571..afe6f807260e 100644 --- a/src/audio/asrc/asrc.c +++ b/src/audio/asrc/asrc.c @@ -128,8 +128,8 @@ static void src_copy_s32(struct comp_dev *dev, { struct comp_data *cd = comp_get_drvdata(dev); int32_t *buf; - int32_t *src = (int32_t *)source->r_ptr; - int32_t *snk = (int32_t *)sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *snk = audio_stream_get_wptr(sink); int n_wrap_src; int n_wrap_snk; int n_copy; @@ -145,16 +145,17 @@ static void src_copy_s32(struct comp_dev *dev, /* Copy input data from source */ buf = (int32_t *)cd->ibuf[0]; - n = cd->source_frames * source->channels; + n = cd->source_frames * audio_stream_get_channels(source); while (n > 0) { - n_wrap_src = (int32_t *)source->end_addr - src; + n_wrap_src = (int32_t *)audio_stream_get_end_addr(source) - src; n_copy = (n < n_wrap_src) ? n : n_wrap_src; for (i = 0; i < n_copy; i++) *buf++ = (*src++) << cd->data_shift; /* Update and check both source and destination for wrap */ n -= n_copy; - src_inc_wrap(&src, source->end_addr, source->size); + src_inc_wrap(&src, audio_stream_get_end_addr(source), + audio_stream_get_size(source)); } /* Run ASRC */ @@ -175,16 +176,17 @@ static void src_copy_s32(struct comp_dev *dev, comp_err(dev, "src_copy_s32(), error %d", ret); buf = (int32_t *)cd->obuf[0]; - n = out_frames * sink->channels; + n = out_frames * audio_stream_get_channels(sink); while (n > 0) { - n_wrap_snk = (int32_t *)sink->end_addr - snk; + n_wrap_snk = (int32_t *)audio_stream_get_end_addr(sink) - snk; n_copy = (n < n_wrap_snk) ? n : n_wrap_snk; for (i = 0; i < n_copy; i++) *snk++ = (*buf++) >> cd->data_shift; /* Update and check both source and destination for wrap */ n -= n_copy; - src_inc_wrap(&snk, sink->end_addr, sink->size); + src_inc_wrap(&snk, audio_stream_get_end_addr(sink), + audio_stream_get_size(sink)); } *n_read = in_frames; @@ -197,8 +199,8 @@ static void src_copy_s16(struct comp_dev *dev, int *n_read, int *n_written) { struct comp_data *cd = comp_get_drvdata(dev); - int16_t *src = (int16_t *)source->r_ptr; - int16_t *snk = (int16_t *)sink->w_ptr; + int16_t *src = audio_stream_get_rptr(source); + int16_t *snk = audio_stream_get_wptr(sink); int16_t *buf; int n_wrap_src; int n_wrap_snk; @@ -214,9 +216,9 @@ static void src_copy_s16(struct comp_dev *dev, /* Copy input data from source */ buf = (int16_t *)cd->ibuf[0]; - n = cd->source_frames * source->channels; + n = cd->source_frames * audio_stream_get_channels(source); while (n > 0) { - n_wrap_src = (int16_t *)source->end_addr - src; + n_wrap_src = (int16_t *)audio_stream_get_end_addr(source) - src; n_copy = (n < n_wrap_src) ? n : n_wrap_src; s_copy = n_copy * sizeof(int16_t); ret = memcpy_s(buf, s_copy, src, s_copy); @@ -226,7 +228,8 @@ static void src_copy_s16(struct comp_dev *dev, n -= n_copy; src += n_copy; buf += n_copy; - src_inc_wrap_s16(&src, source->end_addr, source->size); + src_inc_wrap_s16(&src, audio_stream_get_end_addr(source), + audio_stream_get_size(source)); } /* Run ASRC */ @@ -248,9 +251,9 @@ static void src_copy_s16(struct comp_dev *dev, comp_err(dev, "src_copy_s16(), error %d", ret); buf = (int16_t *)cd->obuf[0]; - n = out_frames * sink->channels; + n = out_frames * audio_stream_get_channels(sink); while (n > 0) { - n_wrap_snk = (int16_t *)sink->end_addr - snk; + n_wrap_snk = (int16_t *)audio_stream_get_end_addr(sink) - snk; n_copy = (n < n_wrap_snk) ? n : n_wrap_snk; s_copy = n_copy * sizeof(int16_t); ret = memcpy_s(snk, s_copy, buf, s_copy); @@ -260,7 +263,8 @@ static void src_copy_s16(struct comp_dev *dev, n -= n_copy; snk += n_copy; buf += n_copy; - src_inc_wrap_s16(&snk, sink->end_addr, sink->size); + src_inc_wrap_s16(&snk, audio_stream_get_end_addr(sink), + audio_stream_get_size(sink)); } *n_read = in_frames; @@ -554,8 +558,8 @@ static int asrc_params(struct comp_dev *dev, sink_c->stream.rate = asrc_get_sink_rate(&cd->ipc_config); /* set source/sink_frames/rate */ - cd->source_rate = source_c->stream.rate; - cd->sink_rate = sink_c->stream.rate; + cd->source_rate = audio_stream_get_rate(&source_c->stream); + cd->sink_rate = audio_stream_get_rate(&sink_c->stream); buffer_release(sink_c); buffer_release(source_c); @@ -750,18 +754,20 @@ static int asrc_prepare(struct comp_dev *dev) sink_c = buffer_acquire(sinkb); /* get source data format and period bytes */ - cd->source_format = source_c->stream.frame_fmt; + cd->source_format = audio_stream_get_frm_fmt(&source_c->stream); source_period_bytes = audio_stream_period_bytes(&source_c->stream, cd->source_frames); /* get sink data format and period bytes */ - cd->sink_format = sink_c->stream.frame_fmt; + cd->sink_format = audio_stream_get_frm_fmt(&sink_c->stream); sink_period_bytes = audio_stream_period_bytes(&sink_c->stream, cd->sink_frames); - if (sink_c->stream.size < dev->ipc_config.periods_sink * sink_period_bytes) { + if (audio_stream_get_size(&sink_c->stream) < + dev->ipc_config.periods_sink * sink_period_bytes) { comp_err(dev, "asrc_prepare(): sink buffer size %d is insufficient < %d * %d", - sink_c->stream.size, dev->ipc_config.periods_sink, sink_period_bytes); + audio_stream_get_size(&sink_c->stream), dev->ipc_config.periods_sink, + sink_period_bytes); ret = -ENOMEM; goto err; } @@ -779,7 +785,7 @@ static int asrc_prepare(struct comp_dev *dev) } /* ASRC supports S16_LE, S24_4LE and S32_LE formats */ - switch (source_c->stream.frame_fmt) { + switch (audio_stream_get_frm_fmt(&source_c->stream)) { case SOF_IPC_FRAME_S16_LE: cd->asrc_func = src_copy_s16; break; @@ -811,8 +817,8 @@ static int asrc_prepare(struct comp_dev *dev) goto err; } - sample_bytes = frame_bytes / source_c->stream.channels; - for (i = 0; i < sourceb->stream.channels; i++) { + sample_bytes = frame_bytes / audio_stream_get_channels(&source_c->stream); + for (i = 0; i < audio_stream_get_channels(&source_c->stream); i++) { cd->ibuf[i] = cd->buf + i * sample_bytes; cd->obuf[i] = cd->ibuf[i] + cd->source_frames_max * frame_bytes; } @@ -820,7 +826,7 @@ static int asrc_prepare(struct comp_dev *dev) /* Get required size and allocate memory for ASRC */ sample_bits = sample_bytes * 8; ret = asrc_get_required_size(dev, &cd->asrc_size, - source_c->stream.channels, + audio_stream_get_channels(&source_c->stream), sample_bits); if (ret) { comp_err(dev, "asrc_prepare(), get_required_size_bytes failed"); @@ -846,7 +852,7 @@ static int asrc_prepare(struct comp_dev *dev) fs_sec = cd->source_rate; } - ret = asrc_initialise(dev, cd->asrc_obj, source_c->stream.channels, + ret = asrc_initialise(dev, cd->asrc_obj, audio_stream_get_channels(&source_c->stream), fs_prim, fs_sec, ASRC_IOF_INTERLEAVED, ASRC_IOF_INTERLEAVED, ASRC_BM_LINEAR, cd->frames, sample_bits, @@ -882,6 +888,9 @@ static int asrc_prepare(struct comp_dev *dev) goto err_free_asrc; } + buffer_release(sink_c); + buffer_release(source_c); + return 0; err_free_asrc: @@ -979,7 +988,7 @@ static void asrc_process(struct comp_dev *dev, struct comp_buffer __sparse_cache int produced = 0; /* consumed bytes are not known at this point */ - buffer_stream_invalidate(source, source->stream.size); + buffer_stream_invalidate(source, audio_stream_get_size(&source->stream)); cd->asrc_func(dev, &source->stream, &sink->stream, &consumed, &produced); buffer_stream_writeback(sink, produced * audio_stream_frame_bytes(&sink->stream)); diff --git a/src/audio/asrc/asrc_farrow.c b/src/audio/asrc/asrc_farrow.c index 3bc51dc2ca55..039b4afe3122 100644 --- a/src/audio/asrc/asrc_farrow.c +++ b/src/audio/asrc/asrc_farrow.c @@ -274,8 +274,8 @@ enum asrc_error_code asrc_get_required_size(struct comp_dev *dev, enum asrc_error_code asrc_initialise(struct comp_dev *dev, struct asrc_farrow *src_obj, int num_channels, - int fs_prim, - int fs_sec, + int32_t fs_prim, + int32_t fs_sec, enum asrc_io_format input_format, enum asrc_io_format output_format, enum asrc_buffer_mode buffer_mode, diff --git a/src/audio/base_fw.c b/src/audio/base_fw.c index 0531e7a60b68..e4806b081b7f 100644 --- a/src/audio/base_fw.c +++ b/src/audio/base_fw.c @@ -11,12 +11,18 @@ #include #include #include +#include #if CONFIG_ACE_V1X_ART_COUNTER || CONFIG_ACE_V1X_RTC_COUNTER #include #include #endif +/* TODO: Remove platform-specific code, see https://github.com/thesofproject/sof/issues/7549 */ +#if defined(CONFIG_SOC_SERIES_INTEL_ACE) || defined(CONFIG_INTEL_ADSP_CAVS) +# define INTEL_ADSP 1 +#endif + LOG_MODULE_REGISTER(basefw, CONFIG_SOF_LOG_LEVEL); /* 0e398c32-5ade-ba4b-93b1-c50432280ee4 */ @@ -196,8 +202,13 @@ static int basefw_mem_state_info(uint32_t *data_offset, char *data) index = 0; tuple_data[index++] = info.free_phys_mem_pages; tuple_data[index++] = info.ebb_state_dword_count; - for (i = 0; i < info.ebb_state_dword_count; i++) + for (i = 0; i < info.ebb_state_dword_count; i++) { +#ifdef INTEL_ADSP tuple_data[index + i] = io_reg_read(SHIM_HSPGCTL(i)); +#else + tuple_data[index + i] = 0; +#endif + } index += info.ebb_state_dword_count; tuple_data[index++] = info.page_alloc_struct.page_alloc_count; @@ -221,7 +232,11 @@ static int basefw_mem_state_info(uint32_t *data_offset, char *data) index = 0; tuple_data[index++] = info.free_phys_mem_pages; tuple_data[index++] = info.ebb_state_dword_count; +#ifdef INTEL_ADSP tuple_data[index++] = io_reg_read(LSPGCTL); +#else + tuple_data[index++] = 0; +#endif tuple_data[index++] = info.page_alloc_struct.page_alloc_count; ptr = (uint16_t *)(tuple_data + index); for (i = 0; i < info.page_alloc_struct.page_alloc_count; i++) diff --git a/src/audio/buffer.c b/src/audio/buffer.c index 3bd41d114a01..11ec261b38ca 100644 --- a/src/audio/buffer.c +++ b/src/audio/buffer.c @@ -27,7 +27,7 @@ DECLARE_SOF_RT_UUID("buffer", buffer_uuid, 0x42544c92, 0x8e92, 0x4e41, 0xb6, 0x79, 0x34, 0x51, 0x9f, 0x1c, 0x1d, 0x28); DECLARE_TR_CTX(buffer_tr, SOF_UUID(buffer_uuid), LOG_LEVEL_INFO); -struct comp_buffer *buffer_alloc(uint32_t size, uint32_t caps, uint32_t align) +struct comp_buffer *buffer_alloc(uint32_t size, uint32_t caps, uint32_t flags, uint32_t align) { struct comp_buffer *buffer; struct comp_buffer __sparse_cache *buffer_c; @@ -59,6 +59,9 @@ struct comp_buffer *buffer_alloc(uint32_t size, uint32_t caps, uint32_t align) return NULL; } + buffer->stream.underrun_permitted = !!(flags & SOF_BUF_UNDERRUN_PERMITTED); + buffer->stream.overrun_permitted = !!(flags & SOF_BUF_OVERRUN_PERMITTED); + list_init(&buffer->source_list); list_init(&buffer->sink_list); @@ -86,13 +89,14 @@ void buffer_zero(struct comp_buffer __sparse_cache *buffer) { buf_dbg(buffer, "stream_zero()"); - bzero(buffer->stream.addr, buffer->stream.size); + bzero(audio_stream_get_addr(&buffer->stream), audio_stream_get_size(&buffer->stream)); if (buffer->caps & SOF_MEM_CAPS_DMA) - dcache_writeback_region((__sparse_force void __sparse_cache *)buffer->stream.addr, - buffer->stream.size); + dcache_writeback_region((__sparse_force void __sparse_cache *) + audio_stream_get_addr(&buffer->stream), + audio_stream_get_size(&buffer->stream)); } -int buffer_set_size(struct comp_buffer __sparse_cache *buffer, uint32_t size) +int buffer_set_size(struct comp_buffer __sparse_cache *buffer, uint32_t size, uint32_t alignment) { void *new_ptr = NULL; @@ -102,16 +106,20 @@ int buffer_set_size(struct comp_buffer __sparse_cache *buffer, uint32_t size) return -EINVAL; } - if (size == buffer->stream.size) + if (size == audio_stream_get_size(&buffer->stream)) return 0; - new_ptr = rbrealloc(buffer->stream.addr, SOF_MEM_FLAG_NO_COPY, - buffer->caps, size, buffer->stream.size); - + if (!alignment) + new_ptr = rbrealloc(audio_stream_get_addr(&buffer->stream), SOF_MEM_FLAG_NO_COPY, + buffer->caps, size, audio_stream_get_size(&buffer->stream)); + else + new_ptr = rbrealloc_align(audio_stream_get_addr(&buffer->stream), + SOF_MEM_FLAG_NO_COPY, buffer->caps, size, + audio_stream_get_size(&buffer->stream), alignment); /* we couldn't allocate bigger chunk */ - if (!new_ptr && size > buffer->stream.size) { + if (!new_ptr && size > audio_stream_get_size(&buffer->stream)) { buf_err(buffer, "resize can't alloc %u bytes type %u", - buffer->stream.size, buffer->caps); + audio_stream_get_size(&buffer->stream), buffer->caps); return -ENOMEM; } @@ -212,7 +220,7 @@ void comp_update_buffer_produce(struct comp_buffer __sparse_cache *buffer, uint3 struct buffer_cb_transact cb_data = { .buffer = buffer, .transaction_amount = bytes, - .transaction_begin_address = buffer->stream.w_ptr, + .transaction_begin_address = audio_stream_get_wptr(&buffer->stream), }; /* return if no bytes */ @@ -234,10 +242,12 @@ void comp_update_buffer_produce(struct comp_buffer __sparse_cache *buffer, uint3 buf_dbg(buffer, "comp_update_buffer_produce(), ((buffer->avail << 16) | buffer->free) = %08x, ((buffer->id << 16) | buffer->size) = %08x", (audio_stream_get_avail_bytes(&buffer->stream) << 16) | audio_stream_get_free_bytes(&buffer->stream), - (buffer->id << 16) | buffer->stream.size); + (buffer->id << 16) | audio_stream_get_size(&buffer->stream)); buf_dbg(buffer, "comp_update_buffer_produce(), ((buffer->r_ptr - buffer->addr) << 16 | (buffer->w_ptr - buffer->addr)) = %08x", - ((char *)buffer->stream.r_ptr - (char *)buffer->stream.addr) << 16 | - ((char *)buffer->stream.w_ptr - (char *)buffer->stream.addr)); + ((char *)audio_stream_get_rptr(&buffer->stream) - + (char *)audio_stream_get_addr(&buffer->stream)) << 16 | + ((char *)audio_stream_get_wptr(&buffer->stream) - + (char *)audio_stream_get_addr(&buffer->stream))); } void comp_update_buffer_consume(struct comp_buffer __sparse_cache *buffer, uint32_t bytes) @@ -245,7 +255,7 @@ void comp_update_buffer_consume(struct comp_buffer __sparse_cache *buffer, uint3 struct buffer_cb_transact cb_data = { .buffer = buffer, .transaction_amount = bytes, - .transaction_begin_address = buffer->stream.r_ptr, + .transaction_begin_address = audio_stream_get_rptr(&buffer->stream), }; /* return if no bytes */ @@ -266,9 +276,11 @@ void comp_update_buffer_consume(struct comp_buffer __sparse_cache *buffer, uint3 buf_dbg(buffer, "comp_update_buffer_consume(), (buffer->avail << 16) | buffer->free = %08x, (buffer->id << 16) | buffer->size = %08x, (buffer->r_ptr - buffer->addr) << 16 | (buffer->w_ptr - buffer->addr)) = %08x", (audio_stream_get_avail_bytes(&buffer->stream) << 16) | audio_stream_get_free_bytes(&buffer->stream), - (buffer->id << 16) | buffer->stream.size, - ((char *)buffer->stream.r_ptr - (char *)buffer->stream.addr) << 16 | - ((char *)buffer->stream.w_ptr - (char *)buffer->stream.addr)); + (buffer->id << 16) | audio_stream_get_size(&buffer->stream), + ((char *)audio_stream_get_rptr(&buffer->stream) - + (char *)audio_stream_get_addr(&buffer->stream)) << 16 | + ((char *)audio_stream_get_wptr(&buffer->stream) - + (char *)audio_stream_get_addr(&buffer->stream))); } void buffer_attach(struct comp_buffer *buffer, struct list_item *head, int dir) diff --git a/src/audio/chain_dma.c b/src/audio/chain_dma.c index 7ef40893d1fb..b8cf7ded072a 100644 --- a/src/audio/chain_dma.c +++ b/src/audio/chain_dma.c @@ -238,7 +238,11 @@ static enum task_state chain_task_run(void *data) * mode task will update read position based on transferred data size to avoid * overwriting valid data and write position by half buffer size. */ - const size_t half_buff_size = cd->dma_buffer->stream.size / 2; + struct comp_buffer __sparse_cache *buffer_c = buffer_acquire(cd->dma_buffer); + const size_t buff_size = audio_stream_get_size(&buffer_c->stream); + const size_t half_buff_size = buff_size / 2; + + buffer_release(buffer_c); if (!cd->first_data_received && host_avail_bytes > half_buff_size) { ret = dma_reload(cd->chan_link->dma->z_dev, @@ -256,7 +260,7 @@ static enum task_state chain_task_run(void *data) const size_t transferred = chain_get_transferred_data_size(link_read_pos, host_read_pos, - cd->dma_buffer->stream.size); + buff_size); ret = dma_reload(cd->chan_host->dma->z_dev, cd->chan_host->index, 0, 0, transferred); @@ -585,7 +589,7 @@ static int chain_task_init(struct comp_dev *dev, uint8_t host_dma_id, uint8_t li fifo_size = ALIGN_UP_INTERNAL(fifo_size, addr_align); - cd->dma_buffer = buffer_alloc(fifo_size, SOF_MEM_CAPS_DMA, addr_align); + cd->dma_buffer = buffer_alloc(fifo_size, SOF_MEM_CAPS_DMA, 0, addr_align); if (!cd->dma_buffer) { comp_err(dev, "chain_task_init(): failed to alloc dma buffer"); @@ -596,8 +600,8 @@ static int chain_task_init(struct comp_dev *dev, uint8_t host_dma_id, uint8_t li /* clear dma buffer */ buffer_c = buffer_acquire(cd->dma_buffer); buffer_zero(buffer_c); - buff_addr = cd->dma_buffer->stream.addr; - buff_size = cd->dma_buffer->stream.size; + buff_addr = audio_stream_get_addr(&buffer_c->stream); + buff_size = audio_stream_get_size(&buffer_c->stream); buffer_release(buffer_c); ret = chain_init(dev, buff_addr, buff_size); diff --git a/src/audio/component.c b/src/audio/component.c index 74501b0fcbdf..ff70573569b4 100644 --- a/src/audio/component.c +++ b/src/audio/component.c @@ -186,8 +186,8 @@ int audio_stream_copy(const struct audio_stream __sparse_cache *source, uint32_t struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { int ssize = audio_stream_sample_bytes(source); /* src fmt == sink fmt */ - ae_int16x4 *src = (ae_int16x4 *)((int8_t *)source->r_ptr + ioffset * ssize); - ae_int16x4 *dst = (ae_int16x4 *)((int8_t *)sink->w_ptr + ooffset * ssize); + ae_int16x4 *src = (ae_int16x4 *)((int8_t *)audio_stream_get_rptr(source) + ioffset * ssize); + ae_int16x4 *dst = (ae_int16x4 *)((int8_t *)audio_stream_get_wptr(sink) + ooffset * ssize); int shorts = samples * ssize >> 1; int shorts_src; int shorts_dst; @@ -231,8 +231,10 @@ int audio_stream_copy(const struct audio_stream __sparse_cache *source, uint32_t struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { int ssize = audio_stream_sample_bytes(source); /* src fmt == sink fmt */ - uint8_t *src = audio_stream_wrap(source, (uint8_t *)source->r_ptr + ioffset * ssize); - uint8_t *snk = audio_stream_wrap(sink, (uint8_t *)sink->w_ptr + ooffset * ssize); + uint8_t *src = audio_stream_wrap(source, (uint8_t *)audio_stream_get_rptr(source) + + ioffset * ssize); + uint8_t *snk = audio_stream_wrap(sink, (uint8_t *)audio_stream_get_wptr(sink) + + ooffset * ssize); size_t bytes = samples * ssize; size_t bytes_src; size_t bytes_snk; @@ -260,7 +262,8 @@ void audio_stream_copy_from_linear(const void *linear_source, int ioffset, { int ssize = audio_stream_sample_bytes(sink); /* src fmt == sink fmt */ uint8_t *src = (uint8_t *)linear_source + ioffset * ssize; - uint8_t *snk = audio_stream_wrap(sink, (uint8_t *)sink->w_ptr + ooffset * ssize); + uint8_t *snk = audio_stream_wrap(sink, (uint8_t *)audio_stream_get_wptr(sink) + + ooffset * ssize); size_t bytes = samples * ssize; size_t bytes_snk; size_t bytes_copied; @@ -279,7 +282,8 @@ void audio_stream_copy_to_linear(const struct audio_stream __sparse_cache *sourc void *linear_sink, int ooffset, unsigned int samples) { int ssize = audio_stream_sample_bytes(source); /* src fmt == sink fmt */ - uint8_t *src = audio_stream_wrap(source, (uint8_t *)source->r_ptr + ioffset * ssize); + uint8_t *src = audio_stream_wrap(source, (uint8_t *)audio_stream_get_rptr(source) + + ioffset * ssize); uint8_t *snk = (uint8_t *)linear_sink + ooffset * ssize; size_t bytes = samples * ssize; size_t bytes_src; diff --git a/src/audio/copier/CMakeLists.txt b/src/audio/copier/CMakeLists.txt index 2a9ff071d146..cc3f717bbde3 100644 --- a/src/audio/copier/CMakeLists.txt +++ b/src/audio/copier/CMakeLists.txt @@ -1,2 +1,6 @@ add_local_sources(sof copier.c copier_hifi.c copier_generic.c) - +if(CONFIG_IPC4_GATEWAY) + add_local_sources(sof + copier_ipcgtw.c + ) +endif() diff --git a/src/audio/copier/copier.c b/src/audio/copier/copier.c index b7b2d8c062a3..69546293f25b 100644 --- a/src/audio/copier/copier.c +++ b/src/audio/copier/copier.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -37,6 +36,12 @@ #include #include #include +#include +#include + +#if CONFIG_ZEPHYR_NATIVE_DRIVERS +#include +#endif static const struct comp_driver comp_copier; @@ -49,11 +54,6 @@ DECLARE_SOF_RT_UUID("copier", copier_comp_uuid, 0x9ba00c83, 0xca12, 0x4a83, DECLARE_TR_CTX(copier_comp_tr, SOF_UUID(copier_comp_uuid), LOG_LEVEL_INFO); -static pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt, - const struct ipc4_audio_format *out_fmt, - enum ipc4_gateway_type type, - enum ipc4_direction_type); - static uint32_t bitmask_to_nibble_channel_map(uint8_t bitmask) { int i; @@ -72,33 +72,64 @@ static uint32_t bitmask_to_nibble_channel_map(uint8_t bitmask) return nibble_map; } -static int create_endpoint_buffer(struct comp_dev *parent_dev, - struct copier_data *cd, - struct comp_ipc_config *config, - const struct ipc4_copier_module_cfg *copier_cfg, - enum ipc4_gateway_type type, - bool create_multi_endpoint_buffer, - int index) +static int copier_set_alh_multi_gtw_channel_map(struct comp_dev *parent_dev, + const struct ipc4_copier_module_cfg *copier_cfg, + int index) +{ + struct copier_data *cd = comp_get_drvdata(parent_dev); + const struct sof_alh_configuration_blob *alh_blob; + uint8_t chan_bitmask; + int channels; + + if (!copier_cfg->gtw_cfg.config_length) { + comp_err(parent_dev, "No ipc4_alh_multi_gtw_cfg found in blob!"); + return -EINVAL; + } + + /* For ALH multi-gateway case, configuration blob contains struct ipc4_alh_multi_gtw_cfg + * with channel map and channels number for each individual gateway. + */ + alh_blob = (const struct sof_alh_configuration_blob *)copier_cfg->gtw_cfg.config_data; + chan_bitmask = alh_blob->alh_cfg.mapping[index].channel_mask; + + channels = popcount(chan_bitmask); + if (channels < 1 || channels > SOF_IPC_MAX_CHANNELS) { + comp_err(parent_dev, "Invalid channels mask: 0x%x", chan_bitmask); + return -EINVAL; + } + + cd->channels[index] = channels; + cd->chan_map[index] = bitmask_to_nibble_channel_map(chan_bitmask); + + return 0; +} + +int create_endpoint_buffer(struct comp_dev *parent_dev, + struct copier_data *cd, + struct comp_ipc_config *config, + const struct ipc4_copier_module_cfg *copier_cfg, + enum ipc4_gateway_type type, + bool create_multi_endpoint_buffer, + int index) { - enum sof_ipc_frame __sparse_cache in_frame_fmt, out_frame_fmt; - enum sof_ipc_frame __sparse_cache in_valid_fmt, out_valid_fmt; + enum sof_ipc_frame in_frame_fmt, out_frame_fmt; + enum sof_ipc_frame in_valid_fmt, out_valid_fmt; enum sof_ipc_frame valid_fmt; struct sof_ipc_buffer ipc_buf; struct comp_buffer *buffer; + struct comp_buffer __sparse_cache *buffer_c; uint32_t buf_size; uint32_t chan_map; int i; audio_stream_fmt_conversion(copier_cfg->base.audio_fmt.depth, copier_cfg->base.audio_fmt.valid_bit_depth, - &in_frame_fmt, - &in_valid_fmt, + &in_frame_fmt, &in_valid_fmt, copier_cfg->base.audio_fmt.s_type); audio_stream_fmt_conversion(copier_cfg->out_fmt.depth, copier_cfg->out_fmt.valid_bit_depth, - &out_frame_fmt, - &out_valid_fmt, + &out_frame_fmt, &out_valid_fmt, copier_cfg->out_fmt.s_type); /* playback case: @@ -155,41 +186,18 @@ static int create_endpoint_buffer(struct comp_dev *parent_dev, if (!buffer) return -ENOMEM; - buffer->stream.channels = copier_cfg->base.audio_fmt.channels_count; - buffer->stream.rate = copier_cfg->base.audio_fmt.sampling_frequency; - buffer->stream.frame_fmt = config->frame_fmt; - buffer->stream.valid_sample_fmt = valid_fmt; - buffer->buffer_fmt = copier_cfg->base.audio_fmt.interleaving_style; - - /* For ALH multi-gateway case, configuration blob contains struct ipc4_alh_multi_gtw_cfg - * with channel map and channels number for each individual gateway. - */ - if (type == ipc4_gtw_alh && is_multi_gateway(copier_cfg->gtw_cfg.node_id) && - !create_multi_endpoint_buffer) { - if (copier_cfg->gtw_cfg.config_length) { - int channels; - const struct sof_alh_configuration_blob *alh_blob = - (const struct sof_alh_configuration_blob *) - copier_cfg->gtw_cfg.config_data; - uint8_t chan_bitmask = alh_blob->alh_cfg.mapping[index].channel_mask; - - channels = popcount(chan_bitmask); - if (channels < 1 || channels > SOF_IPC_MAX_CHANNELS) { - comp_err(parent_dev, "Invalid channels mask: 0x%x", chan_bitmask); - return -EINVAL; - } - buffer->stream.channels = channels; - chan_map = bitmask_to_nibble_channel_map(chan_bitmask); - } else { - comp_err(parent_dev, "No ipc4_alh_multi_gtw_cfg found in blob!"); - return -EINVAL; - } - } + buffer_c = buffer_acquire(buffer); + audio_stream_set_channels(&buffer_c->stream, copier_cfg->base.audio_fmt.channels_count); + audio_stream_set_rate(&buffer_c->stream, copier_cfg->base.audio_fmt.sampling_frequency); + audio_stream_set_frm_fmt(&buffer_c->stream, config->frame_fmt); + audio_stream_set_valid_fmt(&buffer_c->stream, valid_fmt); + buffer_c->buffer_fmt = copier_cfg->base.audio_fmt.interleaving_style; for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) - buffer->chmap[i] = (chan_map >> i * 4) & 0xf; + buffer_c->chmap[i] = (chan_map >> i * 4) & 0xf; - buffer->hw_params_configured = true; + buffer_c->hw_params_configured = true; + buffer_release(buffer_c); if (create_multi_endpoint_buffer) cd->multi_endpoint_buffer = buffer; @@ -211,21 +219,19 @@ static int create_host(struct comp_dev *parent_dev, struct copier_data *cd, struct ipc_config_host ipc_host; struct host_data *hd; int ret; - enum sof_ipc_frame __sparse_cache in_frame_fmt, out_frame_fmt; - enum sof_ipc_frame __sparse_cache in_valid_fmt, out_valid_fmt; + enum sof_ipc_frame in_frame_fmt, out_frame_fmt; + enum sof_ipc_frame in_valid_fmt, out_valid_fmt; config->type = SOF_COMP_HOST; audio_stream_fmt_conversion(copier_cfg->base.audio_fmt.depth, copier_cfg->base.audio_fmt.valid_bit_depth, - &in_frame_fmt, - &in_valid_fmt, + &in_frame_fmt, &in_valid_fmt, copier_cfg->base.audio_fmt.s_type); audio_stream_fmt_conversion(copier_cfg->out_fmt.depth, copier_cfg->out_fmt.valid_bit_depth, - &out_frame_fmt, - &out_valid_fmt, + &out_frame_fmt, &out_valid_fmt, copier_cfg->out_fmt.s_type); if (cd->direction == SOF_IPC_STREAM_PLAYBACK) @@ -273,7 +279,7 @@ static int create_host(struct comp_dev *parent_dev, struct copier_data *cd, return ret; } -static enum sof_ipc_stream_direction +enum sof_ipc_stream_direction get_gateway_direction(enum ipc4_connector_node_id_type node_id_type) { /* WARNING: simple "% 2" formula that was used before does not work for all @@ -300,62 +306,65 @@ static int init_dai(struct comp_dev *parent_dev, struct pipeline *pipeline, struct ipc_config_dai *dai, enum ipc4_gateway_type type, - int index) + int index, int dai_count) { - struct comp_dev *dev; - struct copier_data *cd; + struct copier_data *cd = comp_get_drvdata(parent_dev); + struct dai_data *dd; int ret; - cd = comp_get_drvdata(parent_dev); - ret = create_endpoint_buffer(parent_dev, cd, config, copier, type, false, index); - if (ret < 0) - return ret; + if (cd->direction == SOF_IPC_STREAM_PLAYBACK) { + enum sof_ipc_frame out_frame_fmt, out_valid_fmt; - dev = drv->ops.create(drv, config, dai); - if (!dev) { - ret = -EINVAL; - goto e_buf; + audio_stream_fmt_conversion(copier->out_fmt.depth, + copier->out_fmt.valid_bit_depth, + &out_frame_fmt, + &out_valid_fmt, + copier->out_fmt.s_type); + config->frame_fmt = out_frame_fmt; + pipeline->sink_comp = parent_dev; + cd->bsource_buffer = true; + } else { + enum sof_ipc_frame in_frame_fmt, in_valid_fmt; + + audio_stream_fmt_conversion(copier->base.audio_fmt.depth, + copier->base.audio_fmt.valid_bit_depth, + &in_frame_fmt, &in_valid_fmt, + copier->base.audio_fmt.s_type); + config->frame_fmt = in_frame_fmt; + pipeline->source_comp = parent_dev; } - if (dai->direction == SOF_IPC_STREAM_PLAYBACK) - pipeline->sink_comp = dev; - else - pipeline->source_comp = dev; + parent_dev->ipc_config.frame_fmt = config->frame_fmt; - pipeline->sched_id = config->id; + /* save the channel map and count for ALH multi-gateway */ + if (type == ipc4_gtw_alh && is_multi_gateway(copier->gtw_cfg.node_id)) { + ret = copier_set_alh_multi_gtw_channel_map(parent_dev, copier, index); + if (ret < 0) + return ret; + } - list_init(&dev->bsource_list); - list_init(&dev->bsink_list); + dd = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(*dd)); + if (!dd) + return -ENOMEM; - ret = comp_dai_config(dev, dai, copier); + ret = dai_zephyr_new(dd, parent_dev, dai); if (ret < 0) - goto e_buf; + goto free_dd; - if (dai->direction == SOF_IPC_STREAM_PLAYBACK) { - comp_buffer_connect(dev, config->core, cd->endpoint_buffer[cd->endpoint_num], - PPL_CONN_DIR_BUFFER_TO_COMP); - cd->bsource_buffer = true; - } else { - comp_buffer_connect(dev, config->core, cd->endpoint_buffer[cd->endpoint_num], - PPL_CONN_DIR_COMP_TO_BUFFER); - cd->bsource_buffer = false; - } + pipeline->sched_id = config->id; - cd->converter[IPC4_COPIER_GATEWAY_PIN] = - get_converter_func(&copier->base.audio_fmt, &copier->out_fmt, type, - IPC4_DIRECTION(dai->direction)); - if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) { - comp_err(parent_dev, "failed to get converter type %d, dir %d", - type, dai->direction); - return -EINVAL; - } + cd->dd[index] = dd; + ret = comp_dai_config(cd->dd[index], parent_dev, dai, copier); + if (ret < 0) + goto e_zephyr_free; - cd->endpoint[cd->endpoint_num++] = dev; + cd->endpoint_num++; return 0; - -e_buf: - buffer_free(cd->endpoint_buffer[cd->endpoint_num]); +e_zephyr_free: + dai_zephyr_free(dd); +free_dd: + rfree(dd); return ret; } @@ -376,7 +385,7 @@ static int create_dai(struct comp_dev *parent_dev, struct copier_data *cd, const struct comp_driver *drv; struct ipc_config_dai dai; int dai_count; - int i; + int i, ret; drv = ipc4_get_drv((uint8_t *)&id); if (!drv) @@ -406,6 +415,13 @@ static int create_dai(struct comp_dev *parent_dev, struct copier_data *cd, dai.type = SOF_DAI_INTEL_SSP; dai.is_config_blob = true; type = ipc4_gtw_ssp; + ret = ipc4_find_dma_config(&dai, (uint8_t *)copier->gtw_cfg.config_data, + copier->gtw_cfg.config_length * 4); + if (ret != 0) { + comp_err(parent_dev, "No ssp dma_config found in blob!"); + return -EINVAL; + } + dai.out_fmt = &copier->out_fmt; break; case ipc4_alh_link_output_class: case ipc4_alh_link_input_class: @@ -458,26 +474,41 @@ static int create_dai(struct comp_dev *parent_dev, struct copier_data *cd, dai.type = SOF_DAI_INTEL_DMIC; dai.is_config_blob = true; type = ipc4_gtw_dmic; + + ret = ipc4_find_dma_config(&dai, (uint8_t *)copier->gtw_cfg.config_data, + copier->gtw_cfg.config_length * 4); + if (ret != 0) { + comp_err(parent_dev, "No dmic dma_config found in blob!"); + return -EINVAL; + } + dai.out_fmt = &copier->out_fmt; break; default: return -EINVAL; } for (i = 0; i < dai_count; i++) { - int ret; - dai.dai_index = dai_index[i]; - ret = init_dai(parent_dev, drv, config, copier, pipeline, &dai, type, i); + ret = init_dai(parent_dev, drv, config, copier, pipeline, &dai, type, i, + dai_count); if (ret) { comp_err(parent_dev, "failed to create dai"); return ret; } } + cd->converter[IPC4_COPIER_GATEWAY_PIN] = + get_converter_func(&copier->base.audio_fmt, &copier->out_fmt, type, + IPC4_DIRECTION(dai.direction)); + if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) { + comp_err(parent_dev, "failed to get converter type %d, dir %d", + type, dai.direction); + return -EINVAL; + } + /* create multi_endpoint_buffer for ALH multi-gateway case */ if (dai_count > 1) { - int ret = create_endpoint_buffer(parent_dev, cd, config, copier, type, true, 0); - + ret = create_endpoint_buffer(parent_dev, cd, config, copier, type, true, 0); if (ret < 0) return ret; } @@ -485,74 +516,6 @@ static int create_dai(struct comp_dev *parent_dev, struct copier_data *cd, return 0; } -#if CONFIG_IPC4_GATEWAY -static int create_ipcgtw(struct comp_dev *parent_dev, struct copier_data *cd, - struct comp_ipc_config *config, - const struct ipc4_copier_module_cfg *copier) -{ - const struct comp_driver *drv; - const struct sof_uuid uuid = {0xa814a1ca, 0x0b83, 0x466c, {0x95, 0x87, 0x2f, - 0x35, 0xff, 0x8d, 0x12, 0xe8}}; - int ret; - struct comp_dev *dev; - - cd->ipc_gtw = true; - - drv = ipc4_get_drv((uint8_t *)&uuid); - if (!drv) - return -EINVAL; - - /* create_endpoint_buffer() uses this value to choose between input and - * output formats in copier config to setup buffer. For this purpose - * IPC gateway should be handled similarly as host gateway. - */ - config->type = SOF_COMP_HOST; - - ret = create_endpoint_buffer(parent_dev, cd, config, copier, ipc4_gtw_none, false, 0); - if (ret < 0) - return ret; - - dev = drv->ops.create(drv, config, &copier->gtw_cfg); - if (!dev) { - ret = -EINVAL; - goto e_buf; - } - - list_init(&dev->bsource_list); - list_init(&dev->bsink_list); - - if (cd->direction == SOF_IPC_STREAM_PLAYBACK) { - comp_buffer_connect(dev, config->core, cd->endpoint_buffer[cd->endpoint_num], - PPL_CONN_DIR_COMP_TO_BUFFER); - cd->bsource_buffer = false; - } else { - comp_buffer_connect(dev, config->core, cd->endpoint_buffer[cd->endpoint_num], - PPL_CONN_DIR_BUFFER_TO_COMP); - cd->bsource_buffer = true; - } - - cd->converter[IPC4_COPIER_GATEWAY_PIN] = - get_converter_func(&copier->base.audio_fmt, - &copier->out_fmt, - ipc4_gtw_host, IPC4_DIRECTION(cd->direction)); - if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) { - comp_err(parent_dev, "failed to get converter for IPC gateway, dir %d", - cd->direction); - ret = -EINVAL; - drv->ops.free(dev); - goto e_buf; - } - - cd->endpoint[cd->endpoint_num++] = dev; - - return 0; - -e_buf: - buffer_free(cd->endpoint_buffer[cd->endpoint_num]); - return ret; -} -#endif - /* Playback only */ static int init_pipeline_reg(struct comp_dev *dev) { @@ -673,7 +636,7 @@ static struct comp_dev *copier_new(const struct comp_driver *drv, #if CONFIG_IPC4_GATEWAY case ipc4_ipc_output_class: case ipc4_ipc_input_class: - if (create_ipcgtw(dev, cd, &dev->ipc_config, copier)) { + if (copier_ipcgtw_create(dev, cd, &dev->ipc_config, copier)) { comp_cl_err(&comp_copier, "unable to create IPC gateway"); goto error_cd; } @@ -710,18 +673,29 @@ static void copier_free(struct comp_dev *dev) struct copier_data *cd = comp_get_drvdata(dev); int i; - if (dev->ipc_config.type == SOF_COMP_HOST && !cd->ipc_gtw) { - host_zephyr_free(cd->hd); - rfree(cd->hd); - } - - for (i = 0; i < cd->endpoint_num; i++) { - if (dev->ipc_config.type != SOF_COMP_HOST || cd->ipc_gtw) { - cd->endpoint[i]->drv->ops.free(cd->endpoint[i]); - buffer_free(cd->endpoint_buffer[i]); + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) { + host_zephyr_free(cd->hd); + rfree(cd->hd); + } else { + /* handle gtw case */ + copier_ipcgtw_free(cd); } + break; + case SOF_COMP_DAI: + for (i = 0; i < cd->endpoint_num; i++) { + dai_zephyr_free(cd->dd[i]); + rfree(cd->dd[i]); + } + break; + default: + break; } + if (cd->multi_endpoint_buffer) + buffer_free(cd->multi_endpoint_buffer); + rfree(cd); rfree(dev); } @@ -747,12 +721,12 @@ static bool use_no_container_convert_function(enum sof_ipc_frame in, return false; } -static pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt, - const struct ipc4_audio_format *out_fmt, - enum ipc4_gateway_type type, - enum ipc4_direction_type dir) +pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt, + const struct ipc4_audio_format *out_fmt, + enum ipc4_gateway_type type, + enum ipc4_direction_type dir) { - enum sof_ipc_frame __sparse_cache in, in_valid, out, out_valid; + enum sof_ipc_frame in, in_valid, out, out_valid; audio_stream_fmt_conversion(in_fmt->depth, in_fmt->valid_bit_depth, &in, &in_valid, in_fmt->s_type); @@ -766,13 +740,13 @@ static pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_ return pcm_get_conversion_vc_function(in, in_valid, out, out_valid, type, dir); } -static void copy_single_channel_c16(struct audio_stream __sparse_cache *dst, - int dst_channel, - const struct audio_stream __sparse_cache *src, - int src_channel, int frame_count) +static int copy_single_channel_c16(const struct audio_stream __sparse_cache *src, + unsigned int src_channel, + struct audio_stream __sparse_cache *dst, + unsigned int dst_channel, unsigned int frame_count) { - int16_t *r_ptr = (int16_t *)src->r_ptr + src_channel; - int16_t *w_ptr = (int16_t *)dst->w_ptr + dst_channel; + int16_t *r_ptr = (int16_t *)audio_stream_get_rptr(src) + src_channel; + int16_t *w_ptr = (int16_t *)audio_stream_get_wptr(dst) + dst_channel; /* We have to iterate over frames here. However, tracking frames requires using * of expensive division operations (e.g., inside audio_stream_frames_without_wrap()). @@ -780,7 +754,7 @@ static void copy_single_channel_c16(struct audio_stream __sparse_cache *dst, * is NOT number of samples we need to copy but total samples for all channels. We just * track them to know when to stop. */ - int src_stream_sample_count = frame_count * src->channels; + int src_stream_sample_count = frame_count * audio_stream_get_channels(src); while (src_stream_sample_count) { int src_samples_without_wrap; @@ -791,27 +765,29 @@ static void copy_single_channel_c16(struct audio_stream __sparse_cache *dst, src_samples_without_wrap = audio_stream_samples_without_wrap_s16(src, r_ptr); r_end_ptr = src_stream_sample_count < src_samples_without_wrap ? - r_ptr + src_stream_sample_count : (int16_t *)src->end_addr; + r_ptr + src_stream_sample_count : (int16_t *)audio_stream_get_end_addr(src); r_ptr_before_loop = r_ptr; do { *w_ptr = *r_ptr; - r_ptr += src->channels; - w_ptr += dst->channels; - } while (r_ptr < r_end_ptr && w_ptr < (int16_t *)dst->end_addr); + r_ptr += audio_stream_get_channels(src); + w_ptr += audio_stream_get_channels(dst); + } while (r_ptr < r_end_ptr && w_ptr < (int16_t *)audio_stream_get_end_addr(dst)); src_stream_sample_count -= r_ptr - r_ptr_before_loop; } + + return 0; } -static void copy_single_channel_c32(struct audio_stream __sparse_cache *dst, - int dst_channel, - const struct audio_stream __sparse_cache *src, - int src_channel, int frame_count) +static int copy_single_channel_c32(const struct audio_stream __sparse_cache *src, + unsigned int src_channel, + struct audio_stream __sparse_cache *dst, + unsigned int dst_channel, unsigned int frame_count) { - int32_t *r_ptr = (int32_t *)src->r_ptr + src_channel; - int32_t *w_ptr = (int32_t *)dst->w_ptr + dst_channel; + int32_t *r_ptr = (int32_t *)audio_stream_get_rptr(src) + src_channel; + int32_t *w_ptr = (int32_t *)audio_stream_get_wptr(dst) + dst_channel; /* We have to iterate over frames here. However, tracking frames requires using * of expensive division operations (e.g., inside audio_stream_frames_without_wrap()). @@ -819,7 +795,7 @@ static void copy_single_channel_c32(struct audio_stream __sparse_cache *dst, * is NOT number of samples we need to copy but total samples for all channels. We just * track them to know when to stop. */ - int src_stream_sample_count = frame_count * src->channels; + int src_stream_sample_count = frame_count * audio_stream_get_channels(src); while (src_stream_sample_count) { int src_samples_without_wrap; @@ -830,18 +806,20 @@ static void copy_single_channel_c32(struct audio_stream __sparse_cache *dst, src_samples_without_wrap = audio_stream_samples_without_wrap_s32(src, r_ptr); r_end_ptr = src_stream_sample_count < src_samples_without_wrap ? - r_ptr + src_stream_sample_count : (int32_t *)src->end_addr; + r_ptr + src_stream_sample_count : (int32_t *)audio_stream_get_end_addr(src); r_ptr_before_loop = r_ptr; do { *w_ptr = *r_ptr; - r_ptr += src->channels; - w_ptr += dst->channels; - } while (r_ptr < r_end_ptr && w_ptr < (int32_t *)dst->end_addr); + r_ptr += audio_stream_get_channels(src); + w_ptr += audio_stream_get_channels(dst); + } while (r_ptr < r_end_ptr && w_ptr < (int32_t *)audio_stream_get_end_addr(dst)); src_stream_sample_count -= r_ptr - r_ptr_before_loop; } + + return 0; } static int copier_prepare(struct comp_dev *dev) @@ -864,18 +842,37 @@ static int copier_prepare(struct comp_dev *dev) if (ret == COMP_STATUS_STATE_ALREADY_SET) return PPL_STATUS_PATH_STOP; - if (dev->ipc_config.type == SOF_COMP_HOST && !cd->ipc_gtw) { - ret = host_zephyr_prepare(cd->hd); - if (ret < 0) - return ret; - } + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) { + ret = host_zephyr_prepare(cd->hd); + if (ret < 0) + return ret; + } + break; + case SOF_COMP_DAI: + if (cd->endpoint_num == 1) { + ret = dai_zephyr_config_prepare(cd->dd[0], dev); + if (ret < 0) + return ret; - for (i = 0; i < cd->endpoint_num; i++) { - if (dev->ipc_config.type != SOF_COMP_HOST || cd->ipc_gtw) { - ret = cd->endpoint[i]->drv->ops.prepare(cd->endpoint[i]); + ret = dai_zephyr_prepare(cd->dd[0], dev); if (ret < 0) return ret; + } else { + for (i = 0; i < cd->endpoint_num; i++) { + ret = dai_zephyr_config_prepare(cd->dd[i], dev); + if (ret < 0) + return ret; + + ret = dai_zephyr_prepare(cd->dd[i], dev); + if (ret < 0) + return ret; + } } + break; + default: + break; } if (!cd->endpoint_num) { @@ -892,28 +889,6 @@ static int copier_prepare(struct comp_dev *dev) } } - /* select channel copy func now to avoid unnecessary "switch" logic at processing stage */ - if (cd->multi_endpoint_buffer) { - struct comp_buffer __sparse_cache *buf_c; - int container_size; - - buf_c = buffer_acquire(cd->multi_endpoint_buffer); - container_size = audio_stream_sample_bytes(&buf_c->stream); - buffer_release(buf_c); - - switch (container_size) { - case 2: - cd->copy_single_channel = copy_single_channel_c16; - break; - case 4: - cd->copy_single_channel = copy_single_channel_c32; - break; - default: - comp_err(dev, "Unexpected container size: %d", container_size); - return -EINVAL; - } - } - return 0; } @@ -921,27 +896,26 @@ static int copier_reset(struct comp_dev *dev) { struct copier_data *cd = comp_get_drvdata(dev); struct ipc4_pipeline_registers pipe_reg; - int ret = 0; - int i; + int i, ret = 0; comp_dbg(dev, "copier_reset()"); cd->input_total_data_processed = 0; cd->output_total_data_processed = 0; - if (dev->ipc_config.type == SOF_COMP_HOST && !cd->ipc_gtw) { - if (cd->hd->chan) - notifier_unregister(dev, - cd->hd->chan, NOTIFIER_ID_DMA_COPY); - host_zephyr_reset(cd->hd, dev->state); - } - - for (i = 0; i < cd->endpoint_num; i++) { - if (dev->ipc_config.type != SOF_COMP_HOST || cd->ipc_gtw) { - ret = cd->endpoint[i]->drv->ops.reset(cd->endpoint[i]); - if (ret < 0) - break; - } + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) + host_zephyr_reset(cd->hd, dev->state); + else + copier_ipcgtw_reset(dev); + break; + case SOF_COMP_DAI: + for (i = 0; i < cd->endpoint_num; i++) + dai_zephyr_reset(cd->dd[i], dev); + break; + default: + break; } if (cd->pipeline_reg_offset) { @@ -960,8 +934,8 @@ static int copier_comp_trigger(struct comp_dev *dev, int cmd) struct copier_data *cd = comp_get_drvdata(dev); struct sof_ipc_stream_posn posn; struct comp_dev *dai_copier; - struct copier_data *dai_cd; struct comp_buffer *buffer; + struct comp_buffer __sparse_cache *buffer_c; uint32_t latency; int ret, i; @@ -974,23 +948,28 @@ static int copier_comp_trigger(struct comp_dev *dev, int cmd) if (ret == COMP_STATUS_STATE_ALREADY_SET) return PPL_STATUS_PATH_STOP; - if (dev->ipc_config.type == SOF_COMP_HOST && !cd->ipc_gtw) { - ret = host_zephyr_trigger(cd->hd, dev, cmd); - if (ret < 0) - return ret; - } - - for (i = 0; i < cd->endpoint_num; i++) { - if (dev->ipc_config.type != SOF_COMP_HOST || cd->ipc_gtw) { - ret = cd->endpoint[i]->drv->ops.trigger(cd->endpoint[i], cmd); + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) { + ret = host_zephyr_trigger(cd->hd, dev, cmd); if (ret < 0) - break; + return ret; } + break; + case SOF_COMP_DAI: + for (i = 0; i < cd->endpoint_num; i++) { + ret = dai_zephyr_trigger(cd->dd[i], dev, cmd); + if (ret < 0) + return ret; + } + break; + default: + break; } /* For capture cd->pipeline_reg_offset == 0 */ - if (ret < 0 || !cd->endpoint_num || !cd->pipeline_reg_offset) - return ret; + if (!cd->endpoint_num || !cd->pipeline_reg_offset) + return 0; dai_copier = pipeline_get_dai_comp_latency(dev->pipeline->pipeline_id, &latency); if (!dai_copier) { @@ -1003,10 +982,8 @@ static int copier_comp_trigger(struct comp_dev *dev, int cmd) return 0; } - dai_cd = comp_get_drvdata(dai_copier); /* dai is in another pipeline and it is not prepared or active */ - if (dai_copier->state <= COMP_STATE_READY || - dai_cd->endpoint[IPC4_COPIER_GATEWAY_PIN]->state <= COMP_STATE_READY) { + if (dai_copier->state <= COMP_STATE_READY) { struct ipc4_pipeline_registers pipe_reg; comp_warn(dev, "dai is not ready"); @@ -1054,7 +1031,10 @@ static int copier_comp_trigger(struct comp_dev *dev, int cmd) } buffer = list_first_item(&dai_copier->bsource_list, struct comp_buffer, sink_list); - pipe_reg.stream_start_offset = posn.dai_posn + latency * buffer->stream.size; + buffer_c = buffer_acquire(buffer); + pipe_reg.stream_start_offset = posn.dai_posn + + latency * audio_stream_get_size(&buffer_c->stream); + buffer_release(buffer_c); pipe_reg.stream_end_offset = 0; mailbox_sw_regs_write(cd->pipeline_reg_offset, &pipe_reg, sizeof(pipe_reg)); } else if (cmd == COMP_TRIGGER_PAUSE) { @@ -1077,7 +1057,9 @@ static int copier_comp_trigger(struct comp_dev *dev, int cmd) } buffer = list_first_item(&dai_copier->bsource_list, struct comp_buffer, sink_list); - pipe_reg.stream_start_offset += latency * buffer->stream.size; + buffer_c = buffer_acquire(buffer); + pipe_reg.stream_start_offset += latency * audio_stream_get_size(&buffer_c->stream); + buffer_release(buffer_c); mailbox_sw_regs_write(cd->pipeline_reg_offset, &pipe_reg.stream_start_offset, sizeof(pipe_reg.stream_start_offset)); } @@ -1091,129 +1073,27 @@ static inline struct comp_buffer *get_endpoint_buffer(struct copier_data *cd) cd->endpoint_buffer[IPC4_COPIER_GATEWAY_PIN]; } -static int demux_from_multi_endpoint_buffer(struct copier_data *cd) -{ - struct comp_buffer __sparse_cache *multi_buf_c, *endp_buf_c; - int endp_idx, endp_channel; - uint32_t frame_count, byte_count; - - multi_buf_c = buffer_acquire(cd->multi_endpoint_buffer); - - frame_count = audio_stream_get_avail_frames(&multi_buf_c->stream); - - for (endp_idx = 0; endp_idx < cd->endpoint_num; endp_idx++) { - endp_buf_c = buffer_acquire(cd->endpoint_buffer[endp_idx]); - frame_count = MIN(frame_count, audio_stream_get_free_frames(&endp_buf_c->stream)); - buffer_release(endp_buf_c); - } - - byte_count = frame_count * audio_stream_frame_bytes(&multi_buf_c->stream); - buffer_stream_invalidate(multi_buf_c, byte_count); - - for (endp_idx = 0; endp_idx < cd->endpoint_num; endp_idx++) { - uint32_t bytes_produced; - - endp_buf_c = buffer_acquire(cd->endpoint_buffer[endp_idx]); - - for (endp_channel = 0; endp_channel < endp_buf_c->stream.channels; - endp_channel++) { - int multi_buf_channel = endp_buf_c->chmap[endp_channel]; - - cd->copy_single_channel(&endp_buf_c->stream, endp_channel, - &multi_buf_c->stream, multi_buf_channel, - frame_count); - } - - bytes_produced = frame_count * audio_stream_frame_bytes(&endp_buf_c->stream); - buffer_stream_writeback(endp_buf_c, bytes_produced); - comp_update_buffer_produce(endp_buf_c, bytes_produced); - buffer_release(endp_buf_c); - } - - comp_update_buffer_consume(multi_buf_c, byte_count); - buffer_release(multi_buf_c); - - return 0; -} - -static int mux_into_multi_endpoint_buffer(struct copier_data *cd) -{ - struct comp_buffer __sparse_cache *multi_buf_c, *endp_buf_c; - int endp_idx, endp_channel; - uint32_t frame_count = UINT32_MAX; - uint32_t bytes_produced; - - for (endp_idx = 0; endp_idx < cd->endpoint_num; endp_idx++) { - endp_buf_c = buffer_acquire(cd->endpoint_buffer[endp_idx]); - frame_count = MIN(frame_count, audio_stream_get_avail_frames(&endp_buf_c->stream)); - buffer_release(endp_buf_c); - } - - multi_buf_c = buffer_acquire(cd->multi_endpoint_buffer); - - frame_count = MIN(frame_count, audio_stream_get_free_frames(&multi_buf_c->stream)); - - for (endp_idx = 0; endp_idx < cd->endpoint_num; endp_idx++) { - uint32_t endp_buf_byte_count; - - endp_buf_c = buffer_acquire(cd->endpoint_buffer[endp_idx]); - - endp_buf_byte_count = frame_count * audio_stream_frame_bytes(&endp_buf_c->stream); - buffer_stream_invalidate(endp_buf_c, endp_buf_byte_count); - - for (endp_channel = 0; endp_channel < endp_buf_c->stream.channels; - endp_channel++) { - int multi_buf_channel = endp_buf_c->chmap[endp_channel]; - - cd->copy_single_channel(&multi_buf_c->stream, multi_buf_channel, - &endp_buf_c->stream, endp_channel, - frame_count); - } - - comp_update_buffer_consume(endp_buf_c, endp_buf_byte_count); - buffer_release(endp_buf_c); - } - - bytes_produced = frame_count * audio_stream_frame_bytes(&multi_buf_c->stream); - buffer_stream_writeback(multi_buf_c, bytes_produced); - comp_update_buffer_produce(multi_buf_c, bytes_produced); - - buffer_release(multi_buf_c); - - return 0; -} +static void copier_dma_cb(struct comp_dev *dev, size_t bytes); static int do_endpoint_copy(struct comp_dev *dev) { struct copier_data *cd = comp_get_drvdata(dev); - if (cd->multi_endpoint_buffer) { - int i; - int ret = 0; - - /* multiple gateways on output */ - if (cd->bsource_buffer) { - ret = demux_from_multi_endpoint_buffer(cd); - if (ret < 0) - return ret; - } - - for (i = 0; i < cd->endpoint_num; i++) { - ret = cd->endpoint[i]->drv->ops.copy(cd->endpoint[i]); - if (ret < 0) - return ret; - } - /* multiple gateways on input */ - if (!cd->bsource_buffer) - ret = mux_into_multi_endpoint_buffer(cd); - - return ret; - } else { - if (dev->ipc_config.type == SOF_COMP_HOST && !cd->ipc_gtw) - return host_zephyr_copy(cd->hd, dev); + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) + return host_zephyr_copy(cd->hd, dev, copier_dma_cb); + break; + case SOF_COMP_DAI: + if (cd->endpoint_num == 1) + return dai_zephyr_copy(cd->dd[0], dev, cd->converter); - return cd->endpoint[0]->drv->ops.copy(cd->endpoint[0]); + return dai_zephyr_multi_endpoint_copy(cd->dd, dev, cd->multi_endpoint_buffer, + cd->endpoint_num); + default: + break; } + return 0; } static int do_conversion_copy(struct comp_dev *dev, @@ -1237,7 +1117,7 @@ static int do_conversion_copy(struct comp_dev *dev, buffer_stream_invalidate(src, processed_data->source_bytes); cd->converter[i](&src->stream, 0, &sink->stream, 0, - processed_data->frames * sink->stream.channels); + processed_data->frames * audio_stream_get_channels(&sink->stream)); if (cd->attenuation) { ret = apply_attenuation(dev, cd, sink, processed_data->frames); @@ -1273,8 +1153,18 @@ static int copier_copy(struct comp_dev *dev) comp_dbg(dev, "copier_copy()"); - if (dev->ipc_config.type == SOF_COMP_HOST && !cd->ipc_gtw) - return do_endpoint_copy(dev); + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) + return do_endpoint_copy(dev); + break; + case SOF_COMP_DAI: + if (cd->endpoint_num == 1) + return do_endpoint_copy(dev); + break; + default: + break; + } processed_data.source_bytes = 0; @@ -1345,27 +1235,22 @@ static int copier_copy(struct comp_dev *dev) return ret; } -static void update_internal_comp(struct comp_dev *parent, struct comp_dev *child) -{ - child->period = parent->period; - child->pipeline = parent->pipeline; - child->priority = parent->priority; - child->direction = parent->direction; -} - static void update_buffer_format(struct comp_buffer __sparse_cache *buf_c, const struct ipc4_audio_format *fmt) { + enum sof_ipc_frame valid_fmt, frame_fmt; int i; buf_c->stream.channels = fmt->channels_count; buf_c->stream.rate = fmt->sampling_frequency; audio_stream_fmt_conversion(fmt->depth, fmt->valid_bit_depth, - &buf_c->stream.frame_fmt, - &buf_c->stream.valid_sample_fmt, + &frame_fmt, &valid_fmt, fmt->s_type); + buf_c->stream.frame_fmt = frame_fmt; + buf_c->stream.valid_sample_fmt = valid_fmt; + buf_c->buffer_fmt = fmt->interleaving_style; for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) @@ -1377,13 +1262,10 @@ static void update_buffer_format(struct comp_buffer __sparse_cache *buf_c, /* This is called by DMA driver every time when DMA completes its current * transfer between host and DSP. */ -static void copier_dma_cb(void *arg, enum notify_id type, void *data) +static void copier_dma_cb(struct comp_dev *dev, size_t bytes) { - struct dma_cb_data *next = data; - struct comp_dev *dev = arg; struct copier_data *cd = comp_get_drvdata(dev); struct comp_buffer __sparse_cache *sink; - uint32_t bytes = next->elem.size; int ret, frames; comp_dbg(dev, "copier_dma_cb() %p", dev); @@ -1402,8 +1284,8 @@ static void copier_dma_cb(void *arg, enum notify_id type, void *data) else sink = buffer_acquire(cd->hd->dma_buffer); - frames = bytes / get_sample_bytes(sink->stream.frame_fmt); - frames = frames / sink->stream.channels; + frames = bytes / get_sample_bytes(audio_stream_get_frm_fmt(&sink->stream)); + frames = frames / audio_stream_get_channels(&sink->stream); ret = apply_attenuation(dev, cd, sink, frames); if (ret < 0) @@ -1414,15 +1296,25 @@ static void copier_dma_cb(void *arg, enum notify_id type, void *data) } } +static void copier_notifier_cb(void *arg, enum notify_id type, void *data) +{ + struct dma_cb_data *next = data; + uint32_t bytes = next->elem.size; + + copier_dma_cb(arg, bytes); +} + /* configure the DMA params */ static int copier_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { struct copier_data *cd = comp_get_drvdata(dev); + const struct ipc4_audio_format *in_fmt = &cd->config.base.audio_fmt; + const struct ipc4_audio_format *out_fmt = &cd->config.out_fmt; struct comp_buffer *sink, *source; struct comp_buffer __sparse_cache *sink_c, *source_c; struct list_item *sink_list; - int ret = 0; - int i; + enum sof_ipc_frame in_bits, in_valid_bits, out_bits, out_valid_bits; + int i, ret = 0; comp_dbg(dev, "copier_params()"); @@ -1470,45 +1362,107 @@ static int copier_params(struct comp_dev *dev, struct sof_ipc_stream_params *par buffer_release(source_c); } + /* update params for the DMA buffer */ + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (cd->ipc_gtw || params->direction == SOF_IPC_STREAM_PLAYBACK) + break; + COMPILER_FALLTHROUGH; + case SOF_COMP_DAI: + if (dev->ipc_config.type == SOF_COMP_DAI && + (cd->endpoint_num > 1 || params->direction == SOF_IPC_STREAM_CAPTURE)) + break; + params->buffer.size = cd->config.base.obs; + params->sample_container_bytes = cd->out_fmt->depth / 8; + params->sample_valid_bytes = cd->out_fmt->valid_bit_depth / 8; + break; + default: + break; + } + for (i = 0; i < cd->endpoint_num; i++) { - update_internal_comp(dev, cd->endpoint[i]); + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + if (!cd->ipc_gtw) { + component_set_nearest_period_frames(dev, params->rate); + ret = host_zephyr_params(cd->hd, dev, params, + copier_notifier_cb); - /* For ALH multi-gateway case, params->channels is a total multiplexed - * number of channels. Demultiplexed number of channels for each individual - * gateway comes in blob's struct ipc4_alh_multi_gtw_cfg. - */ - if (cd->multi_endpoint_buffer) { + cd->hd->process = cd->converter[IPC4_COPIER_GATEWAY_PIN]; + } else { + /* handle gtw case */ + ret = copier_ipcgtw_params(cd->ipcgtw_data, dev, params); + } + break; + case SOF_COMP_DAI: + { struct comp_buffer __sparse_cache *buf_c; struct sof_ipc_stream_params demuxed_params = *params; + int container_size; + int j; + + if (cd->endpoint_num == 1) { + ret = dai_zephyr_params(cd->dd[0], dev, params); + + /* + * dai_zephyr_params assigns the conversion function + * based on the input/output formats but does not take + * the valid bits into account. So change the conversion + * function if the valid bits are different from the + * container size. + */ + audio_stream_fmt_conversion(in_fmt->depth, + in_fmt->valid_bit_depth, + &in_bits, &in_valid_bits, + in_fmt->s_type); + audio_stream_fmt_conversion(out_fmt->depth, + out_fmt->valid_bit_depth, + &out_bits, &out_valid_bits, + out_fmt->s_type); + + if (in_bits != in_valid_bits || out_bits != out_valid_bits) + cd->dd[0]->process = + cd->converter[IPC4_COPIER_GATEWAY_PIN]; + break; + } - buf_c = buffer_acquire(cd->endpoint_buffer[i]); - demuxed_params.channels = buf_c->stream.channels; - buffer_release(buf_c); + /* For ALH multi-gateway case, params->channels is a total multiplexed + * number of channels. Demultiplexed number of channels for each individual + * gateway comes in blob's struct ipc4_alh_multi_gtw_cfg. + */ + demuxed_params.channels = cd->channels[i]; - ret = cd->endpoint[i]->drv->ops.params(cd->endpoint[i], - &demuxed_params); - } else { - if (dev->ipc_config.type == SOF_COMP_HOST && !cd->ipc_gtw) { - component_set_nearest_period_frames(dev, params->rate); - if (params->direction == SOF_IPC_STREAM_CAPTURE) { - params->buffer.size = cd->config.base.obs; - params->sample_container_bytes = cd->out_fmt->depth / 8; - params->sample_valid_bytes = - cd->out_fmt->valid_bit_depth / 8; - } + ret = dai_zephyr_params(cd->dd[i], dev, &demuxed_params); + if (ret < 0) + return ret; - ret = host_zephyr_params(cd->hd, dev, params); - if (ret >= 0) - /* set up callback */ - notifier_register(dev, cd->hd->chan, - NOTIFIER_ID_DMA_COPY, copier_dma_cb, 0); + buf_c = buffer_acquire(cd->dd[i]->dma_buffer); + for (j = 0; j < SOF_IPC_MAX_CHANNELS; j++) + buf_c->chmap[j] = (cd->chan_map[i] >> j * 4) & 0xf; + buffer_release(buf_c); - cd->hd->process = cd->converter[IPC4_COPIER_GATEWAY_PIN]; - } else { - ret = cd->endpoint[i]->drv->ops.params(cd->endpoint[i], - params); + /* set channel copy func */ + buf_c = buffer_acquire(cd->multi_endpoint_buffer); + container_size = audio_stream_sample_bytes(&buf_c->stream); + buffer_release(buf_c); + + switch (container_size) { + case 2: + cd->dd[i]->process = copy_single_channel_c16; + break; + case 4: + cd->dd[i]->process = copy_single_channel_c32; + break; + default: + comp_err(dev, "Unexpected container size: %d", container_size); + return -EINVAL; } + break; } + default: + break; + } + if (ret < 0) break; } @@ -1577,7 +1531,7 @@ static int set_attenuation(struct comp_dev *dev, uint32_t data_offset, const cha { struct copier_data *cd = comp_get_drvdata(dev); uint32_t attenuation; - uint32_t __sparse_cache valid_fmt, frame_fmt; + enum sof_ipc_frame valid_fmt, frame_fmt; /* only support attenuation in format of 32bit */ if (data_offset > sizeof(uint32_t)) { @@ -1593,8 +1547,7 @@ static int set_attenuation(struct comp_dev *dev, uint32_t data_offset, const cha audio_stream_fmt_conversion(cd->config.base.audio_fmt.depth, cd->config.base.audio_fmt.valid_bit_depth, - &frame_fmt, - &valid_fmt, + &frame_fmt, &valid_fmt, cd->config.base.audio_fmt.s_type); if (frame_fmt < SOF_IPC_FRAME_S24_4LE) { @@ -1643,10 +1596,13 @@ static int copier_get_large_config(struct comp_dev *dev, uint32_t param_id, struct ipc4_llp_reading_extended llp_ext; struct ipc4_llp_reading llp; + if (cd->ipc_gtw) + return 0; + switch (param_id) { case IPC4_COPIER_MODULE_CFG_PARAM_LLP_READING: if (!cd->endpoint_num || - comp_get_endpoint_type(cd->endpoint[IPC4_COPIER_GATEWAY_PIN]) != + comp_get_endpoint_type(dev) != COMP_ENDPOINT_DAI) { comp_err(dev, "Invalid component type"); return -EINVAL; @@ -1660,13 +1616,13 @@ static int copier_get_large_config(struct comp_dev *dev, uint32_t param_id, *data_offset = sizeof(struct ipc4_llp_reading); memset(&llp, 0, sizeof(llp)); - if (cd->endpoint[IPC4_COPIER_GATEWAY_PIN]->state != COMP_STATE_ACTIVE) { + if (dev->state != COMP_STATE_ACTIVE) { memcpy_s(data, sizeof(llp), &llp, sizeof(llp)); return 0; } /* get llp from dai */ - comp_position(cd->endpoint[IPC4_COPIER_GATEWAY_PIN], &posn); + comp_position(dev, &posn); convert_u64_to_u32s(posn.comp_posn, &llp.llp_l, &llp.llp_u); convert_u64_to_u32s(posn.wallclock, &llp.wclk_l, &llp.wclk_u); @@ -1676,7 +1632,7 @@ static int copier_get_large_config(struct comp_dev *dev, uint32_t param_id, case IPC4_COPIER_MODULE_CFG_PARAM_LLP_READING_EXTENDED: if (!cd->endpoint_num || - comp_get_endpoint_type(cd->endpoint[IPC4_COPIER_GATEWAY_PIN]) != + comp_get_endpoint_type(dev) != COMP_ENDPOINT_DAI) { comp_err(dev, "Invalid component type"); return -EINVAL; @@ -1690,13 +1646,13 @@ static int copier_get_large_config(struct comp_dev *dev, uint32_t param_id, *data_offset = sizeof(struct ipc4_llp_reading_extended); memset(&llp_ext, 0, sizeof(llp_ext)); - if (cd->endpoint[IPC4_COPIER_GATEWAY_PIN]->state != COMP_STATE_ACTIVE) { + if (dev->state != COMP_STATE_ACTIVE) { memcpy_s(data, sizeof(llp_ext), &llp_ext, sizeof(llp_ext)); return 0; } /* get llp from dai */ - comp_position(cd->endpoint[IPC4_COPIER_GATEWAY_PIN], &posn); + comp_position(dev, &posn); convert_u64_to_u32s(posn.comp_posn, &llp_ext.llp_reading.llp_l, &llp_ext.llp_reading.llp_u); @@ -1720,16 +1676,35 @@ static uint64_t copier_get_processed_data(struct comp_dev *dev, uint32_t stream_ { struct copier_data *cd = comp_get_drvdata(dev); uint64_t ret = 0; - bool source = dev->direction == SOF_IPC_STREAM_CAPTURE; + bool source; - if (cd->endpoint_num && cd->bsource_buffer != input) { + /* + * total data processed is calculated as: accumulate all input data in bytes + * from host, then store in host_data structure, this function intend to retrieve + * correct processed data number. + * Due to host already integrated as part of copier, so for host specific case, + * as long as direction is correct, return correct processed data. + * Dai still use ops driver to get data, later, dai will also be integrated + * into copier, this part will be changed again for dai specific. + */ + if (cd->endpoint_num) { if (stream_no < cd->endpoint_num) { - if (dev->ipc_config.type == SOF_COMP_HOST && !cd->ipc_gtw) { - if (source == input) + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + source = dev->direction == SOF_IPC_STREAM_PLAYBACK; + /* only support host, not support ipcgtw case */ + if (!cd->ipc_gtw && source == input) ret = cd->hd->total_data_processed; - } else { + break; + case SOF_COMP_DAI: + source = dev->direction == SOF_IPC_STREAM_CAPTURE; + if (source == input) + ret = cd->dd[0]->total_data_processed; + break; + default: ret = comp_get_total_data_processed(cd->endpoint[stream_no], 0, input); + break; } } } else { @@ -1762,22 +1737,91 @@ static int copier_get_attribute(struct comp_dev *dev, uint32_t type, void *value static int copier_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) { struct copier_data *cd = comp_get_drvdata(dev); - int ret; + int ret = 0; /* Exit if no endpoints */ if (!cd->endpoint_num) return -EINVAL; - if (dev->ipc_config.type == SOF_COMP_HOST && !cd->ipc_gtw) { - posn->host_posn = cd->hd->local_pos; - ret = posn->host_posn; - } else { - ret = comp_position(cd->endpoint[IPC4_COPIER_GATEWAY_PIN], posn); + switch (dev->ipc_config.type) { + case SOF_COMP_HOST: + /* only support host not support gtw case */ + if (!cd->ipc_gtw) { + posn->host_posn = cd->hd->local_pos; + ret = posn->host_posn; + } + break; + case SOF_COMP_DAI: + ret = dai_zephyr_position(cd->dd[0], dev, posn); + break; + default: + break; } /* Return position from the default gateway pin */ return ret; } +static int copier_dai_ts_config_op(struct comp_dev *dev) +{ + struct copier_data *cd = comp_get_drvdata(dev); + struct dai_data *dd = cd->dd[0]; + + return dai_zephyr_ts_config_op(dd, dev); +} + +static int copier_dai_ts_start_op(struct comp_dev *dev) +{ + struct copier_data *cd = comp_get_drvdata(dev); + struct dai_data *dd = cd->dd[0]; + + comp_dbg(dev, "dai_ts_start()"); + + return dai_zephyr_ts_start(dd, dev); +} + +static int copier_dai_ts_get_op(struct comp_dev *dev, struct timestamp_data *tsd) +{ + struct copier_data *cd = comp_get_drvdata(dev); + struct dai_data *dd = cd->dd[0]; + + comp_dbg(dev, "dai_ts_get()"); + + return dai_zephyr_ts_get(dd, dev, tsd); +} + +static int copier_dai_ts_stop_op(struct comp_dev *dev) +{ + struct copier_data *cd = comp_get_drvdata(dev); + struct dai_data *dd = cd->dd[0]; + + comp_dbg(dev, "dai_ts_stop()"); + + return dai_zephyr_ts_stop(dd, dev); +} + +static int copier_get_hw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params, + int dir) +{ + struct copier_data *cd = comp_get_drvdata(dev); + struct dai_data *dd = cd->dd[0]; + + if (dev->ipc_config.type != SOF_COMP_DAI) + return -EINVAL; + + return dai_zephyr_get_hw_params(dd, dev, params, dir); +} + +static int copier_unbind(struct comp_dev *dev, void *data) +{ + struct copier_data *cd = comp_get_drvdata(dev); + struct dai_data *dd = cd->dd[0]; + + if (dev->ipc_config.type == SOF_COMP_DAI) + return dai_zephyr_unbind(dd, dev, data); + + return 0; +} + static const struct comp_driver comp_copier = { .uid = SOF_RT_UUID(copier_comp_uuid), .tctx = &copier_comp_tr, @@ -1794,6 +1838,12 @@ static const struct comp_driver comp_copier = { .get_total_data_processed = copier_get_processed_data, .get_attribute = copier_get_attribute, .position = copier_position, + .dai_ts_config = copier_dai_ts_config_op, + .dai_ts_start = copier_dai_ts_start_op, + .dai_ts_stop = copier_dai_ts_stop_op, + .dai_ts_get = copier_dai_ts_get_op, + .dai_get_hw_params = copier_get_hw_params, + .unbind = copier_unbind, }, }; diff --git a/src/audio/copier/copier_generic.c b/src/audio/copier/copier_generic.c index 54ca4ac922d4..7fa2f361bb0e 100644 --- a/src/audio/copier/copier_generic.c +++ b/src/audio/copier/copier_generic.c @@ -26,11 +26,11 @@ int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, int i; int n; int nmax; - int remaining_samples = frame * sink->stream.channels; - int32_t *dst = sink->stream.r_ptr; + int remaining_samples = frame * audio_stream_get_channels(&sink->stream); + int32_t *dst = audio_stream_get_rptr(&sink->stream); /* only support attenuation in format of 32bit */ - switch (sink->stream.frame_fmt) { + switch (audio_stream_get_frm_fmt(&sink->stream)) { case SOF_IPC_FRAME_S16_LE: comp_err(dev, "16bit sample isn't supported by attenuation"); return -EINVAL; @@ -49,7 +49,8 @@ int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, return 0; default: - comp_err(dev, "unsupported format %d for attenuation", sink->stream.frame_fmt); + comp_err(dev, "unsupported format %d for attenuation", + audio_stream_get_frm_fmt(&sink->stream)); return -EINVAL; } } diff --git a/src/audio/copier/copier_hifi.c b/src/audio/copier/copier_hifi.c index a07721aa0188..4e2894e99490 100644 --- a/src/audio/copier/copier_hifi.c +++ b/src/audio/copier/copier_hifi.c @@ -30,13 +30,13 @@ int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, ae_int32x2 sample; ae_valign uu = AE_ZALIGN64(); ae_valign su = AE_ZALIGN64(); - int remaining_samples = frame * sink->stream.channels; - uint32_t *dst = sink->stream.r_ptr; + int remaining_samples = frame * audio_stream_get_channels(&sink->stream); + uint32_t *dst = audio_stream_get_rptr(&sink->stream); ae_int32x2 *in = (ae_int32x2 *)dst; ae_int32x2 *out = (ae_int32x2 *)dst; /* only support attenuation in format of 32bit */ - switch (sink->stream.frame_fmt) { + switch (audio_stream_get_frm_fmt(&sink->stream)) { case SOF_IPC_FRAME_S16_LE: comp_err(dev, "16bit sample isn't supported by attenuation"); return -EINVAL; @@ -66,7 +66,8 @@ int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, return 0; default: - comp_err(dev, "unsupported format %d for attenuation", sink->stream.frame_fmt); + comp_err(dev, "unsupported format %d for attenuation", + audio_stream_get_frm_fmt(&sink->stream)); return -EINVAL; } } diff --git a/src/audio/ipcgtw.c b/src/audio/copier/copier_ipcgtw.c similarity index 60% rename from src/audio/ipcgtw.c rename to src/audio/copier/copier_ipcgtw.c index 7d96aec94d54..827dc6abce78 100644 --- a/src/audio/ipcgtw.c +++ b/src/audio/copier/copier_ipcgtw.c @@ -8,10 +8,8 @@ #include #include #include -#include #include - -static const struct comp_driver comp_ipcgtw; +#include LOG_MODULE_REGISTER(ipcgtw, CONFIG_SOF_LOG_LEVEL); @@ -21,81 +19,9 @@ DECLARE_SOF_RT_UUID("ipcgw", ipcgtw_comp_uuid, 0xa814a1ca, 0x0b83, 0x466c, DECLARE_TR_CTX(ipcgtw_comp_tr, SOF_UUID(ipcgtw_comp_uuid), LOG_LEVEL_INFO); -/* Host communicates with IPC gateways via global IPC messages. To address a particular - * IPC gateway, its node_id is sent in message payload. Hence we need to keep a list of existing - * IPC gateways and their node_ids to search for a gateway host wants to address. - */ -struct ipcgtw_data { - union ipc4_connector_node_id node_id; - struct comp_dev *dev; - struct list_item item; - - /* IPC gateway buffer size comes in blob at creation time, we keep size here - * to resize buffer later at ipcgtw_params(). - */ - uint32_t buf_size; -}; - /* List of existing IPC gateways */ static struct list_item ipcgtw_list_head = LIST_INIT(ipcgtw_list_head); -static struct comp_dev *ipcgtw_new(const struct comp_driver *drv, - const struct comp_ipc_config *config, - const void *spec) -{ - struct comp_dev *dev; - struct ipcgtw_data *ipcgtw_data; - const struct ipc4_copier_gateway_cfg *gtw_cfg = spec; - const struct ipc4_ipc_gateway_config_blob *blob; - - comp_cl_dbg(&comp_ipcgtw, "ipcgtw_new()"); - - if (!gtw_cfg->config_length) { - comp_cl_err(&comp_ipcgtw, "ipcgtw_new(): empty ipc4_gateway_config_data"); - return NULL; - } - - dev = comp_alloc(drv, sizeof(*dev)); - if (!dev) - return NULL; - dev->ipc_config = *config; - - ipcgtw_data = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*ipcgtw_data)); - if (!ipcgtw_data) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, ipcgtw_data); - - ipcgtw_data->node_id = gtw_cfg->node_id; - ipcgtw_data->dev = dev; - - blob = (const struct ipc4_ipc_gateway_config_blob *) - ((const struct ipc4_gateway_config_data *)gtw_cfg->config_data)->config_blob; - - /* Endpoint buffer is created in copier with size specified in copier config. That buffer - * will be resized to size specified in IPC gateway blob later in ipcgtw_params(). - */ - comp_cl_dbg(&comp_ipcgtw, "ipcgtw_new(): buffer_size: %u", blob->buffer_size); - ipcgtw_data->buf_size = blob->buffer_size; - - list_item_append(&ipcgtw_data->item, &ipcgtw_list_head); - - dev->state = COMP_STATE_READY; - return dev; -} - -static void ipcgtw_free(struct comp_dev *dev) -{ - struct ipcgtw_data *ipcgtw_data = comp_get_drvdata(dev); - - list_item_del(&ipcgtw_data->item); - - rfree(ipcgtw_data); - rfree(dev); -} - static struct comp_dev *find_ipcgtw_by_node_id(union ipc4_connector_node_id node_id) { struct list_item *item; @@ -115,7 +41,7 @@ static inline void audio_stream_copy_bytes_from_linear(const void *linear_source unsigned int bytes) { const uint8_t *src = (const uint8_t *)linear_source; - uint8_t *snk = audio_stream_wrap(sink, (uint8_t *)sink->w_ptr); + uint8_t *snk = audio_stream_wrap(sink, audio_stream_get_wptr(sink)); size_t bytes_snk, bytes_copied; while (bytes) { @@ -132,7 +58,7 @@ static inline void audio_stream_copy_bytes_to_linear(const struct audio_stream __sparse_cache *source, void *linear_sink, unsigned int bytes) { - uint8_t *src = audio_stream_wrap(source, (uint8_t *)source->r_ptr); + uint8_t *src = audio_stream_wrap(source, audio_stream_get_rptr(source)); uint8_t *snk = (uint8_t *)linear_sink; size_t bytes_src, bytes_copied; @@ -161,8 +87,8 @@ static inline struct comp_buffer *get_buffer(struct comp_dev *dev) return list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); } -int ipcgtw_process_cmd(const struct ipc4_ipcgtw_cmd *cmd, - void *reply_payload, uint32_t *reply_payload_size) +int copier_ipcgtw_process(const struct ipc4_ipcgtw_cmd *cmd, + void *reply_payload, uint32_t *reply_payload_size) { const struct ipc4_ipc_gateway_cmd_data *in; struct comp_dev *dev; @@ -171,19 +97,16 @@ int ipcgtw_process_cmd(const struct ipc4_ipcgtw_cmd *cmd, uint32_t data_size; struct ipc4_ipc_gateway_cmd_data_reply *out; - comp_cl_dbg(&comp_ipcgtw, "ipcgtw_process_cmd(): %x %x", - cmd->primary.dat, cmd->extension.dat); - dcache_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_HOSTBOX_BASE, sizeof(struct ipc4_ipc_gateway_cmd_data)); in = (const struct ipc4_ipc_gateway_cmd_data *)MAILBOX_HOSTBOX_BASE; dev = find_ipcgtw_by_node_id(in->node_id); - if (!dev) { - comp_cl_err(&comp_ipcgtw, "ipcgtw_process_cmd(): node_id not found: %x", - in->node_id.dw); - return -EINVAL; - } + if (!dev) + return -ENODEV; + + comp_dbg(dev, "copier_ipcgtw_process(): %x %x", + cmd->primary.dat, cmd->extension.dat); buf = get_buffer(dev); @@ -196,7 +119,7 @@ int ipcgtw_process_cmd(const struct ipc4_ipcgtw_cmd *cmd, * 0 bytes free for SET_DATA. */ buf_c = NULL; - comp_cl_warn(&comp_ipcgtw, "ipcgtw_process_cmd(): no buffer found"); + comp_warn(dev, "copier_ipcgtw_process(): no buffer found"); } out = (struct ipc4_ipc_gateway_cmd_data_reply *)reply_payload; @@ -245,8 +168,8 @@ int ipcgtw_process_cmd(const struct ipc4_ipcgtw_cmd *cmd, break; default: - comp_cl_err(&comp_ipcgtw, "ipcgtw_process_cmd(): unexpected cmd: %u", - (unsigned int)cmd->primary.r.cmd); + comp_err(dev, "copier_ipcgtw_process(): unexpected cmd: %u", + (unsigned int)cmd->primary.r.cmd); if (buf_c) buffer_release(buf_c); return -EINVAL; @@ -257,112 +180,133 @@ int ipcgtw_process_cmd(const struct ipc4_ipcgtw_cmd *cmd, return 0; } -static int ipcgtw_copy(struct comp_dev *dev) -{ - return 0; -} - -static int ipcgtw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) +int copier_ipcgtw_params(struct ipcgtw_data *ipcgtw_data, struct comp_dev *dev, + struct sof_ipc_stream_params *params) { struct comp_buffer *buf; struct comp_buffer __sparse_cache *buf_c; int err; - struct ipcgtw_data *ipcgtw_data = comp_get_drvdata(dev); - comp_cl_dbg(&comp_ipcgtw, "ipcgtw_params()"); + comp_dbg(dev, "ipcgtw_params()"); buf = get_buffer(dev); if (!buf) { - comp_cl_err(&comp_ipcgtw, "ipcgtw_params(): no buffer found"); + comp_err(dev, "ipcgtw_params(): no buffer found"); return -EINVAL; } /* resize buffer to size specified in IPC gateway config blob */ buf_c = buffer_acquire(buf); - err = buffer_set_size(buf_c, ipcgtw_data->buf_size); + err = buffer_set_size(buf_c, ipcgtw_data->buf_size, 0); buffer_release(buf_c); if (err < 0) { - comp_cl_err(&comp_ipcgtw, "ipcgtw_params(): failed to resize buffer to %u bytes", - ipcgtw_data->buf_size); + comp_err(dev, "ipcgtw_params(): failed to resize buffer to %u bytes", + ipcgtw_data->buf_size); return err; } return 0; } -static int ipcgtw_trigger(struct comp_dev *dev, int cmd) +void copier_ipcgtw_reset(struct comp_dev *dev) { - /* copier calls gateway ops.trigger() without checking if it is NULL or not, - * so this handler is needed mostly to prevent crash. - */ - int ret = comp_set_state(dev, cmd); - - if (ret < 0) - return ret; + struct comp_buffer *buf = get_buffer(dev); - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; + if (buf) { + struct comp_buffer __sparse_cache *buf_c = buffer_acquire(buf); - return 0; + audio_stream_reset(&buf_c->stream); + buffer_release(buf_c); + } else { + comp_warn(dev, "ipcgtw_reset(): no buffer found"); + } } -static int ipcgtw_prepare(struct comp_dev *dev) +int copier_ipcgtw_create(struct comp_dev *parent_dev, struct copier_data *cd, + struct comp_ipc_config *config, + const struct ipc4_copier_module_cfg *copier) { - /* copier calls gateway ops.prepare() without checking if it is NULL or not, - * so this handler is needed mostly to prevent crash. + struct ipcgtw_data *ipcgtw_data; + const struct ipc4_copier_gateway_cfg *gtw_cfg; + const struct ipc4_ipc_gateway_config_blob *blob; + int ret; + + gtw_cfg = &copier->gtw_cfg; + if (!gtw_cfg->config_length) { + comp_err(parent_dev, "ipcgtw_create(): empty ipc4_gateway_config_data"); + return -EINVAL; + } + + cd->ipc_gtw = true; + + /* create_endpoint_buffer() uses this value to choose between input and + * output formats in copier config to setup buffer. For this purpose + * IPC gateway should be handled similarly as host gateway. */ - int ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); + config->type = SOF_COMP_HOST; + ret = create_endpoint_buffer(parent_dev, cd, config, copier, ipc4_gtw_none, false, 0); if (ret < 0) return ret; - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; + ipcgtw_data = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*ipcgtw_data)); + if (!ipcgtw_data) { + ret = -ENOMEM; + goto e_buf; + } - return 0; -} + ipcgtw_data->node_id = gtw_cfg->node_id; + ipcgtw_data->dev = parent_dev; -static int ipcgtw_reset(struct comp_dev *dev) -{ - struct comp_buffer *buf = get_buffer(dev); + blob = (const struct ipc4_ipc_gateway_config_blob *) + ((const struct ipc4_gateway_config_data *)gtw_cfg->config_data)->config_blob; - if (buf) { - struct comp_buffer __sparse_cache *buf_c = buffer_acquire(buf); + /* Endpoint buffer is created in copier with size specified in copier config. That buffer + * will be resized to size specified in IPC gateway blob later in ipcgtw_params(). + */ + comp_dbg(parent_dev, "ipcgtw_create(): buffer_size: %u", blob->buffer_size); + ipcgtw_data->buf_size = blob->buffer_size; - audio_stream_reset(&buf_c->stream); - buffer_release(buf_c); + cd->converter[IPC4_COPIER_GATEWAY_PIN] = + get_converter_func(&copier->base.audio_fmt, + &copier->out_fmt, + ipc4_gtw_host, IPC4_DIRECTION(cd->direction)); + if (!cd->converter[IPC4_COPIER_GATEWAY_PIN]) { + comp_err(parent_dev, "failed to get converter for IPC gateway, dir %d", + cd->direction); + ret = -EINVAL; + goto e_ipcgtw; + } + + if (cd->direction == SOF_IPC_STREAM_PLAYBACK) { + comp_buffer_connect(parent_dev, config->core, + cd->endpoint_buffer[cd->endpoint_num], + PPL_CONN_DIR_COMP_TO_BUFFER); + cd->bsource_buffer = false; } else { - comp_cl_warn(&comp_ipcgtw, "ipcgtw_reset(): no buffer found"); + comp_buffer_connect(parent_dev, config->core, + cd->endpoint_buffer[cd->endpoint_num], + PPL_CONN_DIR_BUFFER_TO_COMP); + cd->bsource_buffer = true; } - comp_set_state(dev, COMP_TRIGGER_RESET); + list_item_append(&ipcgtw_data->item, &ipcgtw_list_head); + cd->ipcgtw_data = ipcgtw_data; + cd->endpoint_num++; return 0; + +e_ipcgtw: + rfree(ipcgtw_data); +e_buf: + buffer_free(cd->endpoint_buffer[cd->endpoint_num]); + return ret; } -static const struct comp_driver comp_ipcgtw = { - .uid = SOF_RT_UUID(ipcgtw_comp_uuid), - .tctx = &ipcgtw_comp_tr, - .ops = { - .create = ipcgtw_new, - .free = ipcgtw_free, - .params = ipcgtw_params, - .trigger = ipcgtw_trigger, /* only to prevent copier crash */ - .prepare = ipcgtw_prepare, /* only to prevent copier crash */ - .reset = ipcgtw_reset, - .copy = ipcgtw_copy, - }, -}; - -static SHARED_DATA struct comp_driver_info comp_ipcgtw_info = { - .drv = &comp_ipcgtw, -}; - -UT_STATIC void sys_comp_ipcgtw_init(void) +void copier_ipcgtw_free(struct copier_data *cd) { - comp_register(platform_shared_get(&comp_ipcgtw_info, sizeof(comp_ipcgtw_info))); + list_item_del(&cd->ipcgtw_data->item); + rfree(cd->ipcgtw_data); + buffer_free(cd->endpoint_buffer[0]); } - -DECLARE_MODULE(sys_comp_ipcgtw_init); -SOF_MODULE_INIT(ipcgtw, sys_comp_ipcgtw_init); diff --git a/src/audio/crossover/crossover.c b/src/audio/crossover/crossover.c index a3caf5fc5cd1..72b7a73d3e38 100644 --- a/src/audio/crossover/crossover.c +++ b/src/audio/crossover/crossover.c @@ -610,7 +610,7 @@ static int crossover_copy(struct comp_dev *dev) /* Check for changed configuration */ if (comp_is_new_data_blob_available(cd->model_handler)) { cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL); - ret = crossover_setup(cd, source_c->stream.channels); + ret = crossover_setup(cd, audio_stream_get_channels(&source_c->stream)); if (ret < 0) { comp_err(dev, "crossover_copy(), failed Crossover setup"); goto out; @@ -716,25 +716,25 @@ static int crossover_prepare(struct comp_dev *dev) source_c = buffer_acquire(source); /* Get source data format */ - cd->source_format = source_c->stream.frame_fmt; + cd->source_format = audio_stream_get_frm_fmt(&source_c->stream); /* Validate frame format and buffer size of sinks */ list_for_item(sink_list, &dev->bsink_list) { sink = container_of(sink_list, struct comp_buffer, source_list); sink_c = buffer_acquire(sink); - if (cd->source_format != sink_c->stream.frame_fmt) { + if (cd->source_format != audio_stream_get_frm_fmt(&sink_c->stream)) { comp_err(dev, "crossover_prepare(): Source fmt %d and sink fmt %d are different for sink %d.", - cd->source_format, sink_c->stream.frame_fmt, + cd->source_format, audio_stream_get_frm_fmt(&sink_c->stream), sink_c->pipeline_id); ret = -EINVAL; } else { sink_period_bytes = audio_stream_period_bytes(&sink_c->stream, dev->frames); - if (sink_c->stream.size < sink_period_bytes) { + if (audio_stream_get_size(&sink_c->stream) < sink_period_bytes) { comp_err(dev, "crossover_prepare(), sink %d buffer size %d is insufficient", - sink_c->pipeline_id, sink_c->stream.size); + sink_c->pipeline_id, audio_stream_get_size(&sink_c->stream)); ret = -ENOMEM; } } @@ -747,7 +747,7 @@ static int crossover_prepare(struct comp_dev *dev) comp_info(dev, "crossover_prepare(), source_format=%d, sink_formats=%d, nch=%d", cd->source_format, cd->source_format, - source_c->stream.channels); + audio_stream_get_channels(&source_c->stream)); cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL); @@ -759,7 +759,7 @@ static int crossover_prepare(struct comp_dev *dev) } if (cd->config) { - ret = crossover_setup(cd, source_c->stream.channels); + ret = crossover_setup(cd, audio_stream_get_channels(&source_c->stream)); if (ret < 0) { comp_err(dev, "crossover_prepare(), setup failed"); goto out; diff --git a/src/audio/crossover/crossover_generic.c b/src/audio/crossover/crossover_generic.c index 8df7c52087a2..a4990213e026 100644 --- a/src/audio/crossover/crossover_generic.c +++ b/src/audio/crossover/crossover_generic.c @@ -96,7 +96,7 @@ static void crossover_s16_default_pass(const struct comp_dev *dev, int16_t *x; int32_t *y; int i, j; - int n = source_stream->channels * frames; + int n = audio_stream_get_channels(source_stream) * frames; for (i = 0; i < n; i++) { x = audio_stream_read_frag_s16(source_stream, i); @@ -120,7 +120,7 @@ static void crossover_s32_default_pass(const struct comp_dev *dev, const struct audio_stream __sparse_cache *source_stream = &source->stream; int32_t *x, *y; int i, j; - int n = source_stream->channels * frames; + int n = audio_stream_get_channels(source_stream) * frames; for (i = 0; i < n; i++) { x = audio_stream_read_frag_s32(source_stream, i); @@ -148,7 +148,7 @@ static void crossover_s16_default(const struct comp_dev *dev, int16_t *x, *y; int ch, i, j; int idx; - int nch = source_stream->channels; + int nch = audio_stream_get_channels(source_stream); int32_t out[num_sinks]; for (ch = 0; ch < nch; ch++) { @@ -187,7 +187,7 @@ static void crossover_s24_default(const struct comp_dev *dev, int32_t *x, *y; int ch, i, j; int idx; - int nch = source_stream->channels; + int nch = audio_stream_get_channels(source_stream); int32_t out[num_sinks]; for (ch = 0; ch < nch; ch++) { @@ -226,7 +226,7 @@ static void crossover_s32_default(const struct comp_dev *dev, int32_t *x, *y; int ch, i, j; int idx; - int nch = source_stream->channels; + int nch = audio_stream_get_channels(source_stream); int32_t out[num_sinks]; for (ch = 0; ch < nch; ch++) { diff --git a/src/audio/dai-legacy.c b/src/audio/dai-legacy.c index dafefecda260..ec9d1420d0e0 100644 --- a/src/audio/dai-legacy.c +++ b/src/audio/dai-legacy.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -46,7 +47,7 @@ DECLARE_TR_CTX(dai_comp_tr, SOF_UUID(dai_comp_uuid), LOG_LEVEL_INFO); #if CONFIG_COMP_DAI_GROUP -static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd); +static int dai_comp_trigger_internal(struct dai_data *dd, struct comp_dev *dev, int cmd); static void dai_atomic_trigger(void *arg, enum notify_id type, void *data) { @@ -55,14 +56,12 @@ static void dai_atomic_trigger(void *arg, enum notify_id type, void *data) struct dai_group *group = dd->group; /* Atomic context set by the last DAI to receive trigger command */ - group->trigger_ret = dai_comp_trigger_internal(dev, group->trigger_cmd); + group->trigger_ret = dai_comp_trigger_internal(dd, dev, group->trigger_cmd); } /* Assign DAI to a group */ -int dai_assign_group(struct comp_dev *dev, uint32_t group_id) +int dai_assign_group(struct dai_data *dd, struct comp_dev *dev, uint32_t group_id) { - struct dai_data *dd = comp_get_drvdata(dev); - if (dd->group) { if (dd->group->group_id != group_id) { comp_err(dev, "dai_assign_group(), DAI already in group %d, requested %d", @@ -160,34 +159,14 @@ static void dai_dma_cb(void *arg, enum notify_id type, void *data) buffer_release(dma_buf); } -static struct comp_dev *dai_new(const struct comp_driver *drv, - const struct comp_ipc_config *config, - const void *spec) +int dai_zephyr_new(struct dai_data *dd, struct comp_dev *dev, const struct ipc_config_dai *dai) { - struct comp_dev *dev; - const struct ipc_config_dai *dai = spec; - struct dai_data *dd; uint32_t dir, caps, dma_dev; - comp_cl_dbg(&comp_dai, "dai_new()"); - - dev = comp_alloc(drv, sizeof(*dev)); - if (!dev) - return NULL; - dev->ipc_config = *config; - - dd = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(*dd)); - if (!dd) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, dd); - dd->dai = dai_get(dai->type, dai->dai_index, DAI_CREAT); if (!dd->dai) { comp_cl_err(&comp_dai, "dai_new(): dai_get() failed to create DAI."); - goto error; + return -ENODEV; } dd->dai->dd = dd; dd->ipc_config = *dai; @@ -202,13 +181,44 @@ static struct comp_dev *dai_new(const struct comp_driver *drv, dd->dma = dma_get(dir, caps, dma_dev, DMA_ACCESS_SHARED); if (!dd->dma) { comp_cl_err(&comp_dai, "dai_new(): dma_get() failed to get shared access to DMA."); - goto error; + return -ENODEV; } dma_sg_init(&dd->config.elem_array); dd->xrun = 0; dd->chan = NULL; + return 0; +} + +static struct comp_dev *dai_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + struct comp_dev *dev; + const struct ipc_config_dai *dai = spec; + struct dai_data *dd; + int ret; + + comp_cl_dbg(&comp_dai, "dai_new()"); + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; + + dd = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(*dd)); + if (!dd) { + rfree(dev); + return NULL; + } + + comp_set_drvdata(dev, dd); + + ret = dai_zephyr_new(dd, dev, dai); + if (ret < 0) + goto error; + dev->state = COMP_STATE_READY; return dev; @@ -218,40 +228,46 @@ static struct comp_dev *dai_new(const struct comp_driver *drv, return NULL; } -static void dai_free(struct comp_dev *dev) +void dai_zephyr_free(struct dai_data *dd) { - struct dai_data *dd = comp_get_drvdata(dev); - - if (dd->group) { - notifier_unregister(dev, dd->group, NOTIFIER_ID_DAI_TRIGGER); + if (dd->group) dai_group_put(dd->group); - } if (dd->chan) { - notifier_unregister(dev, dd->chan, NOTIFIER_ID_DMA_COPY); dd->chan->dev_data = NULL; dma_channel_put_legacy(dd->chan); } dma_put(dd->dma); - dai_release_llp_slot(dev); + dai_release_llp_slot(dd); dai_put(dd->dai); if (dd->dai_spec_config) rfree(dd->dai_spec_config); +} + +static void dai_free(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + if (dd->group) + notifier_unregister(dev, dd->group, NOTIFIER_ID_DAI_TRIGGER); + + if (dd->chan) + notifier_unregister(dev, dd->chan, NOTIFIER_ID_DMA_COPY); + + dai_zephyr_free(dd); rfree(dd); rfree(dev); } -static int dai_comp_get_hw_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params, - int dir) +int dai_zephyr_get_hw_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dir) { - struct dai_data *dd = comp_get_drvdata(dev); - int ret = 0; + int ret; comp_dbg(dev, "dai_hw_params()"); @@ -274,6 +290,14 @@ static int dai_comp_get_hw_params(struct comp_dev *dev, return 0; } +static int dai_comp_get_hw_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dir) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + return dai_zephyr_get_hw_params(dd, dev, params, dir); +} + static int dai_comp_hw_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { @@ -298,7 +322,7 @@ static int dai_verify_params(struct comp_dev *dev, { struct sof_ipc_stream_params hw_params; - dai_comp_get_hw_params(dev, &hw_params, params->direction); + comp_dai_get_hw_params(dev, &hw_params, params->direction); /* checks whether pcm parameters match hardware DAI parameter set * during dai_set_config(). If hardware parameter is equal to 0, it @@ -332,8 +356,8 @@ static int dai_playback_params(struct comp_dev *dev, uint32_t period_bytes, struct dma_sg_config *config = &dd->config; struct comp_buffer __sparse_cache *dma_buf = buffer_acquire(dd->dma_buffer), *local_buf = buffer_acquire(dd->local_buffer); - uint32_t local_fmt = local_buf->stream.frame_fmt; - uint32_t dma_fmt = dma_buf->stream.frame_fmt; + uint32_t local_fmt = audio_stream_get_frm_fmt(&local_buf->stream); + uint32_t dma_fmt = audio_stream_get_frm_fmt(&dma_buf->stream); uint32_t fifo; int err = 0; @@ -374,7 +398,7 @@ static int dai_playback_params(struct comp_dev *dev, uint32_t period_bytes, config->direction, period_count, period_bytes, - (uintptr_t)(dma_buf->stream.addr), + (uintptr_t)(audio_stream_get_addr(&dma_buf->stream)), fifo); if (err < 0) comp_err(dev, "dai_playback_params(): dma_sg_alloc() for period_count %d period_bytes %d failed with err = %d", @@ -394,8 +418,8 @@ static int dai_capture_params(struct comp_dev *dev, uint32_t period_bytes, struct dma_sg_config *config = &dd->config; struct comp_buffer __sparse_cache *dma_buf = buffer_acquire(dd->dma_buffer), *local_buf = buffer_acquire(dd->local_buffer); - uint32_t local_fmt = local_buf->stream.frame_fmt; - uint32_t dma_fmt = dma_buf->stream.frame_fmt; + uint32_t local_fmt = audio_stream_get_frm_fmt(&local_buf->stream); + uint32_t dma_fmt = audio_stream_get_frm_fmt(&dma_buf->stream); uint32_t fifo; int err = 0; @@ -447,7 +471,7 @@ static int dai_capture_params(struct comp_dev *dev, uint32_t period_bytes, config->direction, period_count, period_bytes, - (uintptr_t)(dma_buf->stream.addr), + (uintptr_t)(audio_stream_get_addr(&dma_buf->stream)), fifo); if (err < 0) comp_err(dev, "dai_capture_params(): dma_sg_alloc() for period_count %d period_bytes %d failed with err = %d", @@ -460,11 +484,10 @@ static int dai_capture_params(struct comp_dev *dev, uint32_t period_bytes, return err; } -static int dai_params(struct comp_dev *dev, +int dai_zephyr_params(struct dai_data *dd, struct comp_dev *dev, struct sof_ipc_stream_params *params) { struct sof_ipc_stream_params hw_params = *params; - struct dai_data *dd = comp_get_drvdata(dev); struct comp_buffer __sparse_cache *buffer_c; uint32_t frame_size; uint32_t period_count; @@ -477,7 +500,7 @@ static int dai_params(struct comp_dev *dev, comp_dbg(dev, "dai_params()"); /* configure dai_data first */ - err = ipc_dai_data_config(dev); + err = ipc_dai_data_config(dd, dev); if (err < 0) return err; @@ -543,7 +566,7 @@ static int dai_params(struct comp_dev *dev, /* calculate frame size */ frame_size = get_frame_bytes(dev->ipc_config.frame_fmt, - buffer_c->stream.channels); + audio_stream_get_channels(&buffer_c->stream)); buffer_release(buffer_c); @@ -564,7 +587,7 @@ static int dai_params(struct comp_dev *dev, /* alloc DMA buffer or change its size if exists */ if (dd->dma_buffer) { buffer_c = buffer_acquire(dd->dma_buffer); - err = buffer_set_size(buffer_c, buffer_size); + err = buffer_set_size(buffer_c, buffer_size, addr_align); buffer_release(buffer_c); if (err < 0) { @@ -573,7 +596,7 @@ static int dai_params(struct comp_dev *dev, return err; } } else { - dd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, + dd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, 0, addr_align); if (!dd->dma_buffer) { comp_err(dev, "dai_params(): failed to alloc dma buffer"); @@ -598,14 +621,22 @@ static int dai_params(struct comp_dev *dev, dai_capture_params(dev, period_bytes, period_count); } -static int dai_config_prepare(struct comp_dev *dev) +static int dai_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { struct dai_data *dd = comp_get_drvdata(dev); + + comp_dbg(dev, "dai_params()"); + + return dai_zephyr_params(dd, dev, params); +} + +int dai_zephyr_config_prepare(struct dai_data *dd, struct comp_dev *dev) +{ int channel = 0; /* cannot configure DAI while active */ if (dev->state == COMP_STATE_ACTIVE) { - comp_info(dev, "dai_config_prepare(): Component is in active state."); + comp_info(dev, "dai_zephyr_config_prepare(): Component is in active state."); return 0; } @@ -615,13 +646,13 @@ static int dai_config_prepare(struct comp_dev *dev) } if (dd->chan) { - comp_info(dev, "dai_config_prepare(): dma channel index %d already configured", + comp_info(dev, "dai_zephyr_config_prepare(): dma channel index %d already configured", dd->chan->index); return 0; } - channel = dai_config_dma_channel(dev, dd->dai_spec_config); - comp_info(dev, "dai_config_prepare(), channel = %d", channel); + channel = dai_config_dma_channel(dd, dev, dd->dai_spec_config); + comp_info(dev, "dai_zephyr_config_prepare(), channel = %d", channel); /* do nothing for asking for channel free, for compatibility. */ if (channel == DMA_CHAN_INVALID) { @@ -632,14 +663,14 @@ static int dai_config_prepare(struct comp_dev *dev) /* allocate DMA channel */ dd->chan = dma_channel_get_legacy(dd->dma, channel); if (!dd->chan) { - comp_err(dev, "dai_config_prepare(): dma_channel_get() failed"); + comp_err(dev, "dai_zephyr_config_prepare(): dma_channel_get() failed"); dd->chan = NULL; return -EIO; } dd->chan->dev_data = dd; - comp_info(dev, "dai_config_prepare(): new configured dma channel index %d", + comp_info(dev, "dai_zephyr_config_prepare(): new configured dma channel index %d", dd->chan->index); /* setup callback */ @@ -649,24 +680,10 @@ static int dai_config_prepare(struct comp_dev *dev) return 0; } -static int dai_prepare(struct comp_dev *dev) +int dai_zephyr_prepare(struct dai_data *dd, struct comp_dev *dev) { - struct dai_data *dd = comp_get_drvdata(dev); struct comp_buffer __sparse_cache *buffer_c; - int ret = 0; - - comp_info(dev, "dai_prepare()"); - - ret = dai_config_prepare(dev); - if (ret < 0) - return ret; - - ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); - if (ret < 0) - return ret; - - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; + int ret; dd->total_data_processed = 0; @@ -691,7 +708,7 @@ static int dai_prepare(struct comp_dev *dev) if (dd->xrun) { /* after prepare, we have recovered from xrun */ dd->xrun = 0; - return ret; + return 0; } ret = dma_set_config_legacy(dd->chan, &dd->config); @@ -701,19 +718,37 @@ static int dai_prepare(struct comp_dev *dev) return ret; } -static int dai_reset(struct comp_dev *dev) +static int dai_prepare(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); - struct dma_sg_config *config = &dd->config; + int ret; - comp_info(dev, "dai_reset()"); + comp_info(dev, "dai_prepare()"); + + ret = dai_zephyr_config_prepare(dd, dev); + if (ret < 0) + return ret; + + ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); + if (ret < 0) + return ret; + + if (ret == COMP_STATUS_STATE_ALREADY_SET) + return PPL_STATUS_PATH_STOP; + + return dai_zephyr_prepare(dd, dev); +} + +void dai_zephyr_reset(struct dai_data *dd, struct comp_dev *dev) +{ + struct dma_sg_config *config = &dd->config; /* * DMA channel release should be skipped now for DAI's that support the two-step stop option. * It will be done when the host sends the DAI_CONFIG IPC during hw_free. */ if (!dd->delayed_dma_stop) - dai_dma_release(dev); + dai_dma_release(dd, dev); dma_sg_free(&config->elem_array); @@ -725,23 +760,24 @@ static int dai_reset(struct comp_dev *dev) dd->wallclock = 0; dd->total_data_processed = 0; dd->xrun = 0; - comp_set_state(dev, COMP_TRIGGER_RESET); - - return 0; } -static void dai_update_start_position(struct comp_dev *dev) +static int dai_reset(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); - /* update starting wallclock */ - platform_dai_wallclock(dev, &dd->wallclock); + comp_info(dev, "dai_reset()"); + + dai_zephyr_reset(dd, dev); + + comp_set_state(dev, COMP_TRIGGER_RESET); + + return 0; } /* used to pass standard and bespoke command (with data) to component */ -static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) +static int dai_comp_trigger_internal(struct dai_data *dd, struct comp_dev *dev, int cmd) { - struct dai_data *dd = comp_get_drvdata(dev); int ret; comp_dbg(dev, "dai_comp_trigger_internal(), command = %u", cmd); @@ -768,7 +804,7 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) dd->xrun = 0; } - dai_update_start_position(dev); + platform_dai_wallclock(dev, &dd->wallclock); break; case COMP_TRIGGER_RELEASE: /* before release, we clear the buffer data to 0s, @@ -799,7 +835,7 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) dd->xrun = 0; } - dai_update_start_position(dev); + platform_dai_wallclock(dev, &dd->wallclock); break; case COMP_TRIGGER_XRUN: comp_info(dev, "dai_comp_trigger_internal(), XRUN"); @@ -842,17 +878,16 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) return ret; } -static int dai_comp_trigger(struct comp_dev *dev, int cmd) +int dai_zephyr_trigger(struct dai_data *dd, struct comp_dev *dev, int cmd) { - struct dai_data *dd = comp_get_drvdata(dev); struct dai_group *group = dd->group; uint32_t irq_flags; int ret = 0; /* DAI not in a group, use normal trigger */ if (!group) { - comp_dbg(dev, "dai_comp_trigger(), non-atomic trigger"); - return dai_comp_trigger_internal(dev, cmd); + comp_dbg(dev, "dai_zephyr_trigger(), non-atomic trigger"); + return dai_comp_trigger_internal(dd, dev, cmd); } /* DAI is grouped, so only trigger when the entire group is ready */ @@ -861,13 +896,13 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd) /* First DAI to receive the trigger command, * prepare for atomic trigger */ - comp_dbg(dev, "dai_comp_trigger(), begin atomic trigger for group %d", + comp_dbg(dev, "dai_zephyr_trigger(), begin atomic trigger for group %d", group->group_id); group->trigger_cmd = cmd; group->trigger_counter = group->num_dais - 1; } else if (group->trigger_cmd != cmd) { /* Already processing a different trigger command */ - comp_err(dev, "dai_comp_trigger(), already processing atomic trigger"); + comp_err(dev, "dai_zephyr_trigger(), already processing atomic trigger"); ret = -EAGAIN; } else { /* Count down the number of remaining DAIs required @@ -875,7 +910,7 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd) * takes place */ group->trigger_counter--; - comp_dbg(dev, "dai_comp_trigger(), trigger counter %d, group %d", + comp_dbg(dev, "dai_zephyr_trigger(), trigger counter %d, group %d", group->trigger_counter, group->group_id); if (!group->trigger_counter) { @@ -898,6 +933,13 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd) return ret; } +static int dai_comp_trigger(struct comp_dev *dev, int cmd) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + return dai_zephyr_trigger(dd, dev, cmd); +} + /* report xrun occurrence */ static void dai_report_xrun(struct comp_dev *dev, uint32_t bytes) { @@ -916,9 +958,8 @@ static void dai_report_xrun(struct comp_dev *dev, uint32_t bytes) } /* copy and process stream data from source to sink buffers */ -static int dai_copy(struct comp_dev *dev) +int dai_zephyr_copy(struct dai_data *dd, struct comp_dev *dev, pcm_converter_func *converter) { - struct dai_data *dd = comp_get_drvdata(dev); uint32_t dma_fmt; uint32_t sampling; struct comp_buffer __sparse_cache *buf_c; @@ -930,8 +971,6 @@ static int dai_copy(struct comp_dev *dev) uint32_t samples; int ret; - comp_dbg(dev, "dai_copy()"); - /* get data sizes from DMA */ ret = dma_get_data_size_legacy(dd->chan, &avail_bytes, &free_bytes); if (ret < 0) { @@ -941,7 +980,7 @@ static int dai_copy(struct comp_dev *dev) buf_c = buffer_acquire(dd->dma_buffer); - dma_fmt = buf_c->stream.frame_fmt; + dma_fmt = audio_stream_get_frm_fmt(&buf_c->stream); sampling = get_sample_bytes(dma_fmt); buffer_release(buf_c); @@ -966,25 +1005,25 @@ static int dai_copy(struct comp_dev *dev) copy_bytes = samples * sampling; - comp_dbg(dev, "dai_copy(), dir: %d copy_bytes= 0x%x, frames= %d", + comp_dbg(dev, "dai_zephyr_copy(), dir: %d copy_bytes= 0x%x, frames= %d", dev->direction, copy_bytes, - samples / buf_c->stream.channels); + samples / audio_stream_get_channels(&buf_c->stream)); buffer_release(buf_c); /* Check possibility of glitch occurrence */ if (dev->direction == SOF_IPC_STREAM_PLAYBACK && copy_bytes + avail_bytes < dd->period_bytes) - comp_warn(dev, "dai_copy(): Copy_bytes %d + avail bytes %d < period bytes %d, possible glitch", + comp_warn(dev, "dai_zephyr_copy(): Copy_bytes %d + avail bytes %d < period bytes %d, possible glitch", copy_bytes, avail_bytes, dd->period_bytes); else if (dev->direction == SOF_IPC_STREAM_CAPTURE && copy_bytes + free_bytes < dd->period_bytes) - comp_warn(dev, "dai_copy(): Copy_bytes %d + free bytes %d < period bytes %d, possible glitch", + comp_warn(dev, "dai_zephyr_copy(): Copy_bytes %d + free bytes %d < period bytes %d, possible glitch", copy_bytes, free_bytes, dd->period_bytes); /* return if nothing to copy */ if (!copy_bytes) { - comp_warn(dev, "dai_copy(): nothing to copy"); + comp_warn(dev, "dai_zephyr_copy(): nothing to copy"); return 0; } @@ -997,11 +1036,24 @@ static int dai_copy(struct comp_dev *dev) return ret; } - dai_dma_position_update(dev); + dai_dma_position_update(dd, dev); return ret; } +static int dai_copy(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + comp_dbg(dev, "dai_copy()"); + + /* + * DAI devices will only ever have 1 sink, so no need to pass an array of PCM converter + * functions. The default one to use is set in dd->process. + */ + return dai_zephyr_copy(dd, dev, NULL); +} + /** * \brief Get DAI parameters and configure timestamping * \param[in, out] dev DAI device. @@ -1012,9 +1064,8 @@ static int dai_copy(struct comp_dev *dev) * DAI must be prepared before this function is used (for DMA information). If not, an error * is returned. */ -static int dai_ts_config(struct comp_dev *dev) +int dai_zephyr_ts_config_op(struct dai_data *dd, struct comp_dev *dev) { - struct dai_data *dd = comp_get_drvdata(dev); struct timestamp_cfg *cfg = &dd->ts_config; struct ipc_config_dai *dai = &dd->ipc_config; @@ -1036,39 +1087,64 @@ static int dai_ts_config(struct comp_dev *dev) return dd->dai->drv->ts_ops.ts_config(dd->dai, cfg); } -static int dai_ts_start(struct comp_dev *dev) +static int dai_ts_config(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); - comp_dbg(dev, "dai_ts_start()"); + return dai_zephyr_ts_config_op(dd, dev); +} + +int dai_zephyr_ts_start(struct dai_data *dd, struct comp_dev *dev) +{ if (!dd->dai->drv->ts_ops.ts_start) return -ENXIO; return dd->dai->drv->ts_ops.ts_start(dd->dai, &dd->ts_config); } -static int dai_ts_stop(struct comp_dev *dev) +static int dai_ts_start(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); - comp_dbg(dev, "dai_ts_stop()"); + comp_dbg(dev, "dai_ts_start()"); + + return dai_zephyr_ts_start(dd, dev); +} + +int dai_zephyr_ts_stop(struct dai_data *dd, struct comp_dev *dev) +{ if (!dd->dai->drv->ts_ops.ts_stop) return -ENXIO; return dd->dai->drv->ts_ops.ts_stop(dd->dai, &dd->ts_config); } -static int dai_ts_get(struct comp_dev *dev, struct timestamp_data *tsd) +static int dai_ts_stop(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); - comp_dbg(dev, "dai_ts_get()"); + comp_dbg(dev, "dai_ts_stop()"); + + return dai_zephyr_ts_stop(dd, dev); +} + +int dai_zephyr_ts_get(struct dai_data *dd, struct comp_dev *dev, struct timestamp_data *tsd) +{ if (!dd->dai->drv->ts_ops.ts_get) return -ENXIO; return dd->dai->drv->ts_ops.ts_get(dd->dai, &dd->ts_config, tsd); } +static int dai_ts_get(struct comp_dev *dev, struct timestamp_data *tsd) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + comp_dbg(dev, "dai_ts_get()"); + + return dai_zephyr_ts_get(dd, dev, tsd); +} + static uint64_t dai_get_processed_data(struct comp_dev *dev, uint32_t stream_no, bool input) { struct dai_data *dd = comp_get_drvdata(dev); diff --git a/src/audio/dai-zephyr.c b/src/audio/dai-zephyr.c index 327d7811a28a..819c132a6a24 100644 --- a/src/audio/dai-zephyr.c +++ b/src/audio/dai-zephyr.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -51,7 +52,7 @@ DECLARE_TR_CTX(dai_comp_tr, SOF_UUID(dai_comp_uuid), LOG_LEVEL_INFO); #if CONFIG_COMP_DAI_GROUP -static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd); +static int dai_comp_trigger_internal(struct dai_data *dd, struct comp_dev *dev, int cmd); static void dai_atomic_trigger(void *arg, enum notify_id type, void *data) { @@ -60,14 +61,12 @@ static void dai_atomic_trigger(void *arg, enum notify_id type, void *data) struct dai_group *group = dd->group; /* Atomic context set by the last DAI to receive trigger command */ - group->trigger_ret = dai_comp_trigger_internal(dev, group->trigger_cmd); + group->trigger_ret = dai_comp_trigger_internal(dd, dev, group->trigger_cmd); } /* Assign DAI to a group */ -int dai_assign_group(struct comp_dev *dev, uint32_t group_id) +int dai_assign_group(struct dai_data *dd, struct comp_dev *dev, uint32_t group_id) { - struct dai_data *dd = comp_get_drvdata(dev); - if (dd->group) { if (dd->group->group_id != group_id) { comp_err(dev, "dai_assign_group(), DAI already in group %d, requested %d", @@ -144,6 +143,8 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config, case SOF_DAI_INTEL_SSP: cfg.type = is_blob ? DAI_INTEL_SSP_NHLT : DAI_INTEL_SSP; cfg_params = is_blob ? spec_config : &sof_cfg->ssp; + dai_set_link_hda_config(&cfg.link_config, + common_config, cfg_params); break; case SOF_DAI_INTEL_ALH: cfg.type = is_blob ? DAI_INTEL_ALH_NHLT : DAI_INTEL_ALH; @@ -152,6 +153,8 @@ int dai_set_config(struct dai *dai, struct ipc_config_dai *common_config, case SOF_DAI_INTEL_DMIC: cfg.type = is_blob ? DAI_INTEL_DMIC_NHLT : DAI_INTEL_DMIC; cfg_params = is_blob ? spec_config : &sof_cfg->dmic; + dai_set_link_hda_config(&cfg.link_config, + common_config, cfg_params); break; case SOF_DAI_INTEL_HDA: cfg.type = is_blob ? DAI_INTEL_HDA_NHLT : DAI_INTEL_HDA; @@ -219,12 +222,12 @@ static int dai_get_fifo(struct dai *dai, int direction, int stream_id) } /* this is called by DMA driver every time descriptor has completed */ -static enum dma_cb_status dai_dma_cb(struct comp_dev *dev, uint32_t bytes) +static enum dma_cb_status +dai_dma_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes, + pcm_converter_func *converter) { - struct dai_data *dd = comp_get_drvdata(dev); struct comp_buffer __sparse_cache *local_buf, *dma_buf; enum dma_cb_status dma_status = DMA_CB_STATUS_RELOAD; - void *buffer_ptr; int ret; comp_dbg(dev, "dai_dma_cb()"); @@ -256,15 +259,66 @@ static enum dma_cb_status dai_dma_cb(struct comp_dev *dev, uint32_t bytes) if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { ret = dma_buffer_copy_to(local_buf, dma_buf, dd->process, bytes); - - buffer_ptr = local_buf->stream.r_ptr; + buffer_release(local_buf); } else { - ret = dma_buffer_copy_from(dma_buf, local_buf, - dd->process, bytes); + struct list_item *sink_list; + + audio_stream_invalidate(&dma_buf->stream, bytes); + /* + * The PCM converter functions used during DMA buffer copy can never fail, + * so no need to check the return value of dma_buffer_copy_from_no_consume(). + */ + ret = dma_buffer_copy_from_no_consume(dma_buf, local_buf, dd->process, bytes); + buffer_release(local_buf); +#if CONFIG_IPC_MAJOR_4 + /* Skip in case of endpoint DAI devices created by the copier */ + if (converter) { + /* + * copy from DMA buffer to all sink buffers using the right PCM converter + * function + */ + list_for_item(sink_list, &dev->bsink_list) { + struct comp_buffer __sparse_cache *sink_c; + struct comp_dev *sink_dev; + struct comp_buffer *sink; + int j; + + sink = container_of(sink_list, struct comp_buffer, source_list); + + /* this has been handled above already */ + if (sink == dd->local_buffer) + continue; + + sink_c = buffer_acquire(sink); + sink_dev = sink_c->sink; - buffer_ptr = local_buf->stream.w_ptr; + j = IPC4_SINK_QUEUE_ID(sink_c->id); + + if (j >= IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT) { + comp_err(dev, "Sink queue ID: %d >= max output pin count: %d\n", + j, IPC4_COPIER_MODULE_OUTPUT_PINS_COUNT); + ret = -EINVAL; + goto err; + } + + if (!converter[j]) { + comp_err(dev, "No PCM converter for sink queue %d\n", j); + ret = -EINVAL; + goto err; + } + + if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE) + ret = dma_buffer_copy_from_no_consume(dma_buf, sink_c, + converter[j], bytes); +err: + buffer_release(sink_c); + } + } +#endif + audio_stream_consume(&dma_buf->stream, bytes); } + local_buf = buffer_acquire(dd->local_buffer); /* assert dma_buffer_copy succeed */ if (ret < 0) { struct comp_buffer __sparse_cache *source_c, *sink_c; @@ -290,34 +344,81 @@ static enum dma_cb_status dai_dma_cb(struct comp_dev *dev, uint32_t bytes) return dma_status; } -static struct comp_dev *dai_new(const struct comp_driver *drv, - const struct comp_ipc_config *config, - const void *spec) +/* this is called by DMA driver every time descriptor has completed */ +static enum dma_cb_status +dai_dma_multi_endpoint_cb(struct dai_data *dd, struct comp_dev *dev, uint32_t frames, + struct comp_buffer *multi_endpoint_buffer) { - struct comp_dev *dev; - const struct ipc_config_dai *dai_cfg = spec; - struct dai_data *dd; - uint32_t dir; + struct comp_buffer __sparse_cache *multi_buf_c, *dma_buf; + enum dma_cb_status dma_status = DMA_CB_STATUS_RELOAD; + uint32_t i, bytes; - comp_cl_dbg(&comp_dai, "dai_new()"); + comp_dbg(dev, "dai_dma_multi_endpoint_cb()"); - dev = comp_alloc(drv, sizeof(*dev)); - if (!dev) - return NULL; - dev->ipc_config = *config; + /* stop dma copy for pause/stop/xrun */ + if (dev->state != COMP_STATE_ACTIVE || dd->xrun) { + /* stop the DAI */ + dai_trigger_op(dd->dai, COMP_TRIGGER_STOP, dev->direction); - dd = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(*dd)); - if (!dd) { - rfree(dev); - return NULL; + /* tell DMA not to reload */ + dma_status = DMA_CB_STATUS_END; } - comp_set_drvdata(dev, dd); + dma_buf = buffer_acquire(dd->dma_buffer); + + /* is our pipeline handling an XRUN ? */ + if (dd->xrun) { + /* make sure we only playback silence during an XRUN */ + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + /* fill buffer with silence */ + buffer_zero(dma_buf); + buffer_release(dma_buf); + + return dma_status; + } + + multi_buf_c = buffer_acquire(multi_endpoint_buffer); + + bytes = frames * audio_stream_frame_bytes(&dma_buf->stream); + if (dev->direction == SOF_IPC_STREAM_CAPTURE) + audio_stream_invalidate(&dma_buf->stream, bytes); + + /* copy all channels one by one */ + for (i = 0; i < audio_stream_get_channels(&dma_buf->stream); i++) { + uint32_t multi_buf_channel = dma_buf->chmap[i]; + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + dd->process(&multi_buf_c->stream, multi_buf_channel, + &dma_buf->stream, i, frames); + else + dd->process(&dma_buf->stream, i, &multi_buf_c->stream, + multi_buf_channel, frames); + } + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + audio_stream_writeback(&dma_buf->stream, bytes); + audio_stream_produce(&dma_buf->stream, bytes); + } else { + audio_stream_consume(&dma_buf->stream, bytes); + } + + /* update host position (in bytes offset) for drivers */ + dd->total_data_processed += bytes; + buffer_release(multi_buf_c); + buffer_release(dma_buf); + + return dma_status; +} + +int dai_zephyr_new(struct dai_data *dd, struct comp_dev *dev, + const struct ipc_config_dai *dai_cfg) +{ + uint32_t dir; dd->dai = dai_get(dai_cfg->type, dai_cfg->dai_index, DAI_CREAT); if (!dd->dai) { - comp_cl_err(&comp_dai, "dai_new(): dai_get() failed to create DAI."); - goto error; + comp_err(dev, "dai_new(): dai_get() failed to create DAI."); + return -ENODEV; } dd->ipc_config = *dai_cfg; @@ -328,8 +429,9 @@ static struct comp_dev *dai_new(const struct comp_driver *drv, dd->dma = dma_get(dir, dd->dai->dma_caps, dd->dai->dma_dev, DMA_ACCESS_SHARED); if (!dd->dma) { - comp_cl_err(&comp_dai, "dai_new(): dma_get() failed to get shared access to DMA."); - goto error; + dai_put(dd->dai); + comp_err(dev, "dai_new(): dma_get() failed to get shared access to DMA."); + return -ENODEV; } k_spinlock_init(&dd->dai->lock); @@ -338,23 +440,51 @@ static struct comp_dev *dai_new(const struct comp_driver *drv, dd->xrun = 0; dd->chan = NULL; + return 0; +} + +static struct comp_dev *dai_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) +{ + struct comp_dev *dev; + const struct ipc_config_dai *dai_cfg = spec; + struct dai_data *dd; + int ret; + + comp_cl_dbg(&comp_dai, "dai_new()"); + + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + + dev->ipc_config = *config; + + dd = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(*dd)); + if (!dd) + goto e_data; + + comp_set_drvdata(dev, dd); + + ret = dai_zephyr_new(dd, dev, dai_cfg); + if (ret < 0) + goto error; + dev->state = COMP_STATE_READY; + return dev; error: rfree(dd); +e_data: rfree(dev); return NULL; } -static void dai_free(struct comp_dev *dev) +void dai_zephyr_free(struct dai_data *dd) { - struct dai_data *dd = comp_get_drvdata(dev); - - if (dd->group) { - notifier_unregister(dev, dd->group, NOTIFIER_ID_DAI_TRIGGER); + if (dd->group) dai_group_put(dd->group); - } if (dd->chan) { dma_release_channel(dd->dma->z_dev, dd->chan->index); @@ -363,24 +493,33 @@ static void dai_free(struct comp_dev *dev) dma_put(dd->dma); - dai_release_llp_slot(dev); + dai_release_llp_slot(dd); dai_put(dd->dai); rfree(dd->dai_spec_config); +} + +static void dai_free(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + if (dd->group) + notifier_unregister(dev, dd->group, NOTIFIER_ID_DAI_TRIGGER); + + dai_zephyr_free(dd); + rfree(dd); rfree(dev); } -static int dai_comp_get_hw_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params, - int dir) +int dai_zephyr_get_hw_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dir) { - struct dai_data *dd = comp_get_drvdata(dev); struct dai_config cfg; int ret; - comp_dbg(dev, "dai_hw_params()"); + comp_dbg(dev, "dai_zephyr_get_hw_params()"); ret = dai_config_get(dd->dai->dev, &cfg, dir); if (ret) @@ -401,12 +540,21 @@ static int dai_comp_get_hw_params(struct comp_dev *dev, return ret; } +static int dai_comp_get_hw_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params, + int dir) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + return dai_zephyr_get_hw_params(dd, dev, params, dir); +} + static int dai_verify_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { struct sof_ipc_stream_params hw_params; int ret; - ret = dai_comp_get_hw_params(dev, &hw_params, params->direction); + ret = comp_dai_get_hw_params(dev, &hw_params, params->direction); if (ret < 0) { comp_err(dev, "dai_verify_params(): dai_verify_params failed ret %d", ret); return ret; @@ -437,18 +585,17 @@ static int dai_verify_params(struct comp_dev *dev, struct sof_ipc_stream_params } /* set component audio SSP and DMA configuration */ -static int dai_playback_params(struct comp_dev *dev, uint32_t period_bytes, - uint32_t period_count) +static int dai_playback_params(struct dai_data *dd, struct comp_dev *dev, uint32_t period_bytes, + int32_t period_count) { - struct dai_data *dd = comp_get_drvdata(dev); struct dma_sg_config *config = &dd->config; struct dma_config *dma_cfg; struct dma_block_config *dma_block_cfg; struct dma_block_config *prev = NULL; struct comp_buffer __sparse_cache *dma_buf = buffer_acquire(dd->dma_buffer), *local_buf = buffer_acquire(dd->local_buffer); - uint32_t local_fmt = local_buf->stream.frame_fmt; - uint32_t dma_fmt = dma_buf->stream.frame_fmt; + uint32_t local_fmt = audio_stream_get_frm_fmt(&local_buf->stream); + uint32_t dma_fmt = audio_stream_get_frm_fmt(&dma_buf->stream); uint32_t fifo, max_block_count, buf_size; int i, err = 0; @@ -509,7 +656,7 @@ static int dai_playback_params(struct comp_dev *dev, uint32_t period_bytes, config->direction, period_count, period_bytes, - (uintptr_t)(dma_buf->stream.addr), + (uintptr_t)audio_stream_get_addr(&dma_buf->stream), fifo); if (err < 0) { comp_err(dev, "dai_playback_params(): dma_sg_alloc() for period_count %d period_bytes %d failed with err = %d", @@ -575,18 +722,17 @@ static int dai_playback_params(struct comp_dev *dev, uint32_t period_bytes, return err; } -static int dai_capture_params(struct comp_dev *dev, uint32_t period_bytes, +static int dai_capture_params(struct dai_data *dd, struct comp_dev *dev, uint32_t period_bytes, uint32_t period_count) { - struct dai_data *dd = comp_get_drvdata(dev); struct dma_sg_config *config = &dd->config; struct dma_config *dma_cfg; struct dma_block_config *dma_block_cfg; struct dma_block_config *prev = NULL; struct comp_buffer __sparse_cache *dma_buf = buffer_acquire(dd->dma_buffer), *local_buf = buffer_acquire(dd->local_buffer); - uint32_t local_fmt = local_buf->stream.frame_fmt; - uint32_t dma_fmt = dma_buf->stream.frame_fmt; + uint32_t local_fmt = audio_stream_get_frm_fmt(&local_buf->stream); + uint32_t dma_fmt = audio_stream_get_frm_fmt(&dma_buf->stream); uint32_t fifo, max_block_count, buf_size; int i, err = 0; @@ -664,7 +810,7 @@ static int dai_capture_params(struct comp_dev *dev, uint32_t period_bytes, config->direction, period_count, period_bytes, - (uintptr_t)(dma_buf->stream.addr), + (uintptr_t)audio_stream_get_addr(&dma_buf->stream), fifo); if (err < 0) { comp_err(dev, "dai_capture_params(): dma_sg_alloc() for period_count %d period_bytes %d failed with err = %d", @@ -730,10 +876,10 @@ static int dai_capture_params(struct comp_dev *dev, uint32_t period_bytes, return err; } -static int dai_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) +int dai_zephyr_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params) { struct sof_ipc_stream_params hw_params = *params; - struct dai_data *dd = comp_get_drvdata(dev); struct comp_buffer __sparse_cache *buffer_c; uint32_t frame_size; uint32_t period_count; @@ -743,16 +889,14 @@ static int dai_params(struct comp_dev *dev, struct sof_ipc_stream_params *params uint32_t align; int err; - comp_dbg(dev, "dai_params()"); - /* configure dai_data first */ - err = ipc_dai_data_config(dev); + err = ipc_dai_data_config(dd, dev); if (err < 0) return err; err = dai_verify_params(dev, params); if (err < 0) { - comp_err(dev, "dai_params(): pcm params verification failed."); + comp_err(dev, "dai_zephyr_params(): pcm params verification failed."); return -EINVAL; } @@ -767,13 +911,13 @@ static int dai_params(struct comp_dev *dev, struct sof_ipc_stream_params *params /* check if already configured */ if (dev->state == COMP_STATE_PREPARE) { - comp_info(dev, "dai_params() component has been already configured."); + comp_info(dev, "dai_zephyr_params() component has been already configured."); return 0; } /* can set params on only init state */ if (dev->state != COMP_STATE_READY) { - comp_err(dev, "dai_params(): Component is in state %d, expected COMP_STATE_READY.", + comp_err(dev, "dai_zephyr_params(): Component is in state %d, expected COMP_STATE_READY.", dev->state); return -EINVAL; } @@ -781,36 +925,31 @@ static int dai_params(struct comp_dev *dev, struct sof_ipc_stream_params *params err = dma_get_attribute(dd->dma->z_dev, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT, &addr_align); if (err < 0) { - comp_err(dev, "dai_params(): could not get dma buffer address alignment, err = %d", + comp_err(dev, "dai_zephyr_params(): could not get dma buffer address alignment, err = %d", err); return err; } err = dma_get_attribute(dd->dma->z_dev, DMA_ATTR_BUFFER_SIZE_ALIGNMENT, &align); if (err < 0 || !align) { - comp_err(dev, "dai_params(): no valid dma buffer alignment, err = %d, align = %u", + comp_err(dev, "dai_zephyr_params(): no valid dma buffer alignment, err = %d, align = %u", err, align); return -EINVAL; } period_count = dd->dma->plat_data.period_count; if (!period_count) { - comp_err(dev, "dai_params(): no valid dma buffer period count"); + comp_err(dev, "dai_zephyr_params(): no valid dma buffer period count"); return -EINVAL; } - buffer_c = buffer_acquire(dd->local_buffer); - /* calculate frame size */ - frame_size = get_frame_bytes(dev->ipc_config.frame_fmt, - buffer_c->stream.channels); - - buffer_release(buffer_c); + frame_size = get_frame_bytes(dev->ipc_config.frame_fmt, params->channels); /* calculate period size */ period_bytes = dev->frames * frame_size; if (!period_bytes) { - comp_err(dev, "dai_params(): invalid period_bytes."); + comp_err(dev, "dai_zephyr_params(): invalid period_bytes."); return -EINVAL; } @@ -824,19 +963,19 @@ static int dai_params(struct comp_dev *dev, struct sof_ipc_stream_params *params /* alloc DMA buffer or change its size if exists */ if (dd->dma_buffer) { buffer_c = buffer_acquire(dd->dma_buffer); - err = buffer_set_size(buffer_c, buffer_size); + err = buffer_set_size(buffer_c, buffer_size, addr_align); buffer_release(buffer_c); if (err < 0) { - comp_err(dev, "dai_params(): buffer_set_size() failed, buffer_size = %u", + comp_err(dev, "dai_zephyr_params(): buffer_set_size() failed, buffer_size = %u", buffer_size); return err; } } else { - dd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, + dd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, 0, addr_align); if (!dd->dma_buffer) { - comp_err(dev, "dai_params(): failed to alloc dma buffer"); + comp_err(dev, "dai_zephyr_params(): failed to alloc dma buffer"); return -ENOMEM; } @@ -854,18 +993,26 @@ static int dai_params(struct comp_dev *dev, struct sof_ipc_stream_params *params } return dev->direction == SOF_IPC_STREAM_PLAYBACK ? - dai_playback_params(dev, period_bytes, period_count) : - dai_capture_params(dev, period_bytes, period_count); + dai_playback_params(dd, dev, period_bytes, period_count) : + dai_capture_params(dd, dev, period_bytes, period_count); } -static int dai_config_prepare(struct comp_dev *dev) +static int dai_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { struct dai_data *dd = comp_get_drvdata(dev); + + comp_dbg(dev, "dai_params()"); + + return dai_zephyr_params(dd, dev, params); +} + +int dai_zephyr_config_prepare(struct dai_data *dd, struct comp_dev *dev) +{ int channel; /* cannot configure DAI while active */ if (dev->state == COMP_STATE_ACTIVE) { - comp_info(dev, "dai_config_prepare(): Component is in active state."); + comp_info(dev, "dai_zephyr_config_prepare(): Component is in active state."); return 0; } @@ -875,13 +1022,13 @@ static int dai_config_prepare(struct comp_dev *dev) } if (dd->chan) { - comp_info(dev, "dai_config_prepare(): dma channel index %d already configured", + comp_info(dev, "dai_zephyr_config_prepare(): dma channel index %d already configured", dd->chan->index); return 0; } - channel = dai_config_dma_channel(dev, dd->dai_spec_config); - comp_dbg(dev, "dai_config_prepare(), channel = %d", channel); + channel = dai_config_dma_channel(dd, dev, dd->dai_spec_config); + comp_dbg(dev, "dai_zephyr_config_prepare(), channel = %d", channel); /* do nothing for asking for channel free, for compatibility. */ if (channel == DMA_CHAN_INVALID) { @@ -892,7 +1039,7 @@ static int dai_config_prepare(struct comp_dev *dev) /* get DMA channel */ channel = dma_request_channel(dd->dma->z_dev, &channel); if (channel < 0) { - comp_err(dev, "dai_config_prepare(): dma_request_channel() failed"); + comp_err(dev, "dai_zephyr_config_prepare(): dma_request_channel() failed"); dd->chan = NULL; return -EIO; } @@ -900,41 +1047,27 @@ static int dai_config_prepare(struct comp_dev *dev) dd->chan = &dd->dma->chan[channel]; dd->chan->dev_data = dd; - comp_dbg(dev, "dai_config_prepare(): new configured dma channel index %d", + comp_dbg(dev, "dai_zephyr_config_prepare(): new configured dma channel index %d", dd->chan->index); return 0; } -static int dai_prepare(struct comp_dev *dev) +int dai_zephyr_prepare(struct dai_data *dd, struct comp_dev *dev) { - struct dai_data *dd = comp_get_drvdata(dev); struct comp_buffer __sparse_cache *buffer_c; int ret; - comp_dbg(dev, "dai_prepare()"); - - ret = dai_config_prepare(dev); - if (ret < 0) - return ret; - - ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); - if (ret < 0) - return ret; - - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; - dd->total_data_processed = 0; if (!dd->chan) { - comp_err(dev, "dai_prepare(): Missing dd->chan."); + comp_err(dev, "dai_zephyr_prepare(): Missing dd->chan."); comp_set_state(dev, COMP_TRIGGER_RESET); return -EINVAL; } if (!dd->config.elem_array.elems) { - comp_err(dev, "dai_prepare(): Missing dd->config.elem_array.elems."); + comp_err(dev, "dai_zephyr_prepare(): Missing dd->config.elem_array.elems."); comp_set_state(dev, COMP_TRIGGER_RESET); return -EINVAL; } @@ -948,7 +1081,7 @@ static int dai_prepare(struct comp_dev *dev) if (dd->xrun) { /* after prepare, we have recovered from xrun */ dd->xrun = 0; - return ret; + return 0; } ret = dma_config(dd->chan->dma->z_dev, dd->chan->index, dd->z_config); @@ -958,19 +1091,37 @@ static int dai_prepare(struct comp_dev *dev) return ret; } -static int dai_reset(struct comp_dev *dev) +static int dai_prepare(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); - struct dma_sg_config *config = &dd->config; + int ret; - comp_dbg(dev, "dai_reset()"); + comp_dbg(dev, "dai_prepare()"); + + ret = dai_zephyr_config_prepare(dd, dev); + if (ret < 0) + return ret; + + ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); + if (ret < 0) + return ret; + + if (ret == COMP_STATUS_STATE_ALREADY_SET) + return PPL_STATUS_PATH_STOP; + + return dai_zephyr_prepare(dd, dev); +} + +void dai_zephyr_reset(struct dai_data *dd, struct comp_dev *dev) +{ + struct dma_sg_config *config = &dd->config; /* * DMA channel release should be skipped now for DAI's that support the two-step stop * option. It will be done when the host sends the DAI_CONFIG IPC during hw_free. */ if (!dd->delayed_dma_stop) - dai_dma_release(dev); + dai_dma_release(dd, dev); dma_sg_free(&config->elem_array); if (dd->z_config) { @@ -987,35 +1138,28 @@ static int dai_reset(struct comp_dev *dev) dd->wallclock = 0; dd->total_data_processed = 0; dd->xrun = 0; - comp_set_state(dev, COMP_TRIGGER_RESET); - - return 0; } -static void dai_update_start_position(struct comp_dev *dev) +static int dai_reset(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); - /* update starting wallclock */ - platform_dai_wallclock(dev, &dd->wallclock); + comp_dbg(dev, "dai_reset()"); + + dai_zephyr_reset(dd, dev); + + comp_set_state(dev, COMP_TRIGGER_RESET); + + return 0; } /* used to pass standard and bespoke command (with data) to component */ -static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) +static int dai_comp_trigger_internal(struct dai_data *dd, struct comp_dev *dev, int cmd) { - struct dai_data *dd = comp_get_drvdata(dev); - int prev_state = dev->state; - int ret; + int ret = 0; comp_dbg(dev, "dai_comp_trigger_internal(), command = %u", cmd); - ret = comp_set_state(dev, cmd); - if (ret < 0) - return ret; - - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; - switch (cmd) { case COMP_TRIGGER_START: comp_dbg(dev, "dai_comp_trigger_internal(), START"); @@ -1032,7 +1176,7 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) dd->xrun = 0; } - dai_update_start_position(dev); + platform_dai_wallclock(dev, &dd->wallclock); break; case COMP_TRIGGER_RELEASE: /* before release, we clear the buffer data to 0s, @@ -1050,11 +1194,9 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) /* only start the DAI if we are not XRUN handling */ if (dd->xrun == 0) { /* recover valid start position */ - if (dev->state == COMP_STATE_ACTIVE) { - ret = dma_stop(dd->chan->dma->z_dev, dd->chan->index); - if (ret < 0) - return ret; - } + ret = dma_stop(dd->chan->dma->z_dev, dd->chan->index); + if (ret < 0) + return ret; /* dma_config needed after stop */ ret = dma_config(dd->chan->dma->z_dev, dd->chan->index, dd->z_config); @@ -1071,7 +1213,7 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) dd->xrun = 0; } - dai_update_start_position(dev); + platform_dai_wallclock(dev, &dd->wallclock); break; case COMP_TRIGGER_XRUN: comp_info(dev, "dai_comp_trigger_internal(), XRUN"); @@ -1103,21 +1245,11 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) case COMP_TRIGGER_PAUSE: comp_dbg(dev, "dai_comp_trigger_internal(), PAUSE"); #if CONFIG_COMP_DAI_TRIGGER_ORDER_REVERSE - if (prev_state == COMP_STATE_ACTIVE) { - ret = dma_suspend(dd->chan->dma->z_dev, dd->chan->index); - } else { - comp_warn(dev, "dma was stopped earlier"); - ret = 0; - } + ret = dma_suspend(dd->chan->dma->z_dev, dd->chan->index); dai_trigger_op(dd->dai, cmd, dev->direction); #else dai_trigger_op(dd->dai, cmd, dev->direction); - if (prev_state == COMP_STATE_ACTIVE) { - ret = dma_suspend(dd->chan->dma->z_dev, dd->chan->index); - } else { - comp_warn(dev, "dma was stopped earlier"); - ret = 0; - } + ret = dma_suspend(dd->chan->dma->z_dev, dd->chan->index); #endif break; case COMP_TRIGGER_PRE_START: @@ -1133,17 +1265,16 @@ static int dai_comp_trigger_internal(struct comp_dev *dev, int cmd) return ret; } -static int dai_comp_trigger(struct comp_dev *dev, int cmd) +int dai_zephyr_trigger(struct dai_data *dd, struct comp_dev *dev, int cmd) { - struct dai_data *dd = comp_get_drvdata(dev); struct dai_group *group = dd->group; uint32_t irq_flags; int ret = 0; /* DAI not in a group, use normal trigger */ if (!group) { - comp_dbg(dev, "dai_comp_trigger(), non-atomic trigger"); - return dai_comp_trigger_internal(dev, cmd); + comp_dbg(dev, "dai_zephyr_trigger(), non-atomic trigger"); + return dai_comp_trigger_internal(dd, dev, cmd); } /* DAI is grouped, so only trigger when the entire group is ready */ @@ -1152,13 +1283,13 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd) /* First DAI to receive the trigger command, * prepare for atomic trigger */ - comp_dbg(dev, "dai_comp_trigger(), begin atomic trigger for group %d", + comp_dbg(dev, "dai_zephyr_trigger(), begin atomic trigger for group %d", group->group_id); group->trigger_cmd = cmd; group->trigger_counter = group->num_dais - 1; } else if (group->trigger_cmd != cmd) { /* Already processing a different trigger command */ - comp_err(dev, "dai_comp_trigger(), already processing atomic trigger"); + comp_err(dev, "dai_zephyr_trigger(), already processing atomic trigger"); ret = -EAGAIN; } else { /* Count down the number of remaining DAIs required @@ -1166,7 +1297,7 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd) * takes place */ group->trigger_counter--; - comp_dbg(dev, "dai_comp_trigger(), trigger counter %d, group %d", + comp_dbg(dev, "dai_zephyr_trigger(), trigger counter %d, group %d", group->trigger_counter, group->group_id); if (!group->trigger_counter) { @@ -1189,10 +1320,16 @@ static int dai_comp_trigger(struct comp_dev *dev, int cmd) return ret; } -/* report xrun occurrence */ -static void dai_report_xrun(struct comp_dev *dev, uint32_t bytes) +static int dai_comp_trigger(struct comp_dev *dev, int cmd) { struct dai_data *dd = comp_get_drvdata(dev); + + return dai_zephyr_trigger(dd, dev, cmd); +} + +/* report xrun occurrence */ +static void dai_report_xrun(struct dai_data *dd, struct comp_dev *dev, uint32_t bytes) +{ struct comp_buffer __sparse_cache *buf_c = buffer_acquire(dd->local_buffer); if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { @@ -1206,10 +1343,162 @@ static void dai_report_xrun(struct comp_dev *dev, uint32_t bytes) buffer_release(buf_c); } +/* process and copy stream data from multiple DMA source buffers to sink buffer */ +int dai_zephyr_multi_endpoint_copy(struct dai_data **dd, struct comp_dev *dev, + struct comp_buffer *multi_endpoint_buffer, + int num_endpoints) +{ + struct comp_buffer __sparse_cache *buf_c; + uint32_t avail_bytes = UINT32_MAX; + uint32_t free_bytes = UINT32_MAX; + uint32_t frames; + uint32_t src_frames, sink_frames; + uint32_t frame_bytes; + int ret, i; + int direction; + + if (!num_endpoints || !dd || !multi_endpoint_buffer) + return 0; + + buf_c = buffer_acquire(dd[0]->dma_buffer); + frame_bytes = audio_stream_frame_bytes(&buf_c->stream); + buffer_release(buf_c); + + direction = dev->direction; + + /* calculate min available/free from all endpoint DMA buffers */ + for (i = 0; i < num_endpoints; i++) { + struct dma_status stat; + + /* get data sizes from DMA */ + ret = dma_get_status(dd[i]->chan->dma->z_dev, dd[i]->chan->index, &stat); + switch (ret) { + case 0: + break; + case -EPIPE: + /* DMA status can return -EPIPE and current status content if xrun occurs */ + if (direction == SOF_IPC_STREAM_PLAYBACK) + comp_dbg(dev, "dai_zephyr_multi_endpoint_copy(): dma_get_status() underrun occurred, endpoint: %d ret = %u", + i, ret); + else + comp_dbg(dev, "dai_zephyr_multi_endpoint_copy(): dma_get_status() overrun occurred, enpdoint: %d ret = %u", + i, ret); + break; + default: + return ret; + } + + avail_bytes = MIN(avail_bytes, stat.pending_length); + free_bytes = MIN(free_bytes, stat.free); + } + + buf_c = buffer_acquire(multi_endpoint_buffer); + /* calculate minimum size to copy */ + if (direction == SOF_IPC_STREAM_PLAYBACK) { + src_frames = audio_stream_get_avail_frames(&buf_c->stream); + sink_frames = free_bytes / frame_bytes; + } else { + src_frames = avail_bytes / frame_bytes; + sink_frames = audio_stream_get_free_frames(&buf_c->stream); + } + buffer_release(buf_c); + + frames = MIN(src_frames, sink_frames); + + /* limit bytes per copy to one period for the whole pipeline in order to avoid high load + * spike if FAST_MODE is enabled, then one period limitation is omitted. All dd's have the + * same period_bytes, so use the period_bytes from dd[0] + */ + if (!(dd[0]->ipc_config.feature_mask & BIT(IPC4_COPIER_FAST_MODE))) + frames = MIN(frames, dd[0]->period_bytes / frame_bytes); + comp_dbg(dev, "dai_zephyr_multi_endpoint_copy(), dir: %d copy frames= 0x%x", + dev->direction, frames); + + /* return if nothing to copy */ + if (!frames) { + comp_warn(dev, "dai_zephyr_multi_endpoint_copy(): nothing to copy"); + return 0; + } + + if (direction == SOF_IPC_STREAM_PLAYBACK) { + buf_c = buffer_acquire(multi_endpoint_buffer); + frame_bytes = audio_stream_frame_bytes(&buf_c->stream); + buffer_stream_invalidate(buf_c, frames * frame_bytes); + buffer_release(buf_c); + } + + for (i = 0; i < num_endpoints; i++) { + enum dma_cb_status status; + uint32_t copy_bytes; + + /* trigger optional DAI_TRIGGER_COPY which prepares dai to copy */ + ret = dai_trigger(dd[i]->dai->dev, direction, DAI_TRIGGER_COPY); + if (ret < 0) + comp_warn(dev, "dai_zephyr_multi_endpoint_copy(): dai trigger copy failed"); + + status = dai_dma_multi_endpoint_cb(dd[i], dev, frames, multi_endpoint_buffer); + if (status == DMA_CB_STATUS_END) + dma_stop(dd[i]->chan->dma->z_dev, dd[i]->chan->index); + + buf_c = buffer_acquire(dd[i]->dma_buffer); + copy_bytes = frames * audio_stream_frame_bytes(&buf_c->stream); + buffer_release(buf_c); + ret = dma_reload(dd[i]->chan->dma->z_dev, dd[i]->chan->index, 0, 0, copy_bytes); + if (ret < 0) { + dai_report_xrun(dd[i], dev, copy_bytes); + return ret; + } + + dai_dma_position_update(dd[i], dev); + } + + buf_c = buffer_acquire(multi_endpoint_buffer); + frame_bytes = audio_stream_frame_bytes(&buf_c->stream); + if (direction == SOF_IPC_STREAM_PLAYBACK) { + comp_update_buffer_consume(buf_c, frames * frame_bytes); + } else { + buffer_stream_writeback(buf_c, frames * frame_bytes); + comp_update_buffer_produce(buf_c, frames * frame_bytes); + } + buffer_release(buf_c); + + return 0; +} + +static void set_new_local_buffer(struct dai_data *dd, struct comp_dev *dev) +{ + struct comp_buffer __sparse_cache *dma_buf = buffer_acquire(dd->dma_buffer); + struct comp_buffer __sparse_cache *local_buf; + uint32_t dma_fmt = audio_stream_get_frm_fmt(&dma_buf->stream); + uint32_t local_fmt; + + buffer_release(dma_buf); + + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) + dd->local_buffer = list_first_item(&dev->bsource_list, + struct comp_buffer, + sink_list); + else + dd->local_buffer = list_first_item(&dev->bsink_list, + struct comp_buffer, + source_list); + + local_buf = buffer_acquire(dd->local_buffer); + local_fmt = audio_stream_get_frm_fmt(&local_buf->stream); + buffer_release(local_buf); + + dd->process = pcm_get_conversion_function(local_fmt, dma_fmt); + + if (!dd->process) { + comp_err(dev, "converter function NULL: local fmt %d dma fmt %d\n", + local_fmt, dma_fmt); + dd->local_buffer = NULL; + } +} + /* copy and process stream data from source to sink buffers */ -static int dai_copy(struct comp_dev *dev) +int dai_zephyr_copy(struct dai_data *dd, struct comp_dev *dev, pcm_converter_func *converter) { - struct dai_data *dd = comp_get_drvdata(dev); uint32_t dma_fmt; uint32_t sampling; struct comp_buffer __sparse_cache *buf_c; @@ -1219,11 +1508,9 @@ static int dai_copy(struct comp_dev *dev) uint32_t copy_bytes = 0; uint32_t src_samples; uint32_t sink_samples; - uint32_t samples; + uint32_t samples = UINT32_MAX; int ret; - comp_dbg(dev, "dai_copy()"); - /* get data sizes from DMA */ ret = dma_get_status(dd->chan->dma->z_dev, dd->chan->index, &stat); switch (ret) { @@ -1232,11 +1519,11 @@ static int dai_copy(struct comp_dev *dev) case -EPIPE: /* DMA status can return -EPIPE and current status content if xrun occurs */ if (dev->direction == SOF_IPC_STREAM_PLAYBACK) - comp_dbg(dev, "dai_copy(): dma_get_status() underrun occurred, ret = %u", - ret); + comp_dbg(dev, "dai_zephyr_copy(): dma_get_status() underrun occurred, ret = %u", + ret); else - comp_dbg(dev, "dai_copy(): dma_get_status() overrun occurred, ret = %u", - ret); + comp_dbg(dev, "dai_zephyr_copy(): dma_get_status() overrun occurred, ret = %u", + ret); break; default: return ret; @@ -1247,22 +1534,66 @@ static int dai_copy(struct comp_dev *dev) buf_c = buffer_acquire(dd->dma_buffer); - dma_fmt = buf_c->stream.frame_fmt; + dma_fmt = audio_stream_get_frm_fmt(&buf_c->stream); sampling = get_sample_bytes(dma_fmt); buffer_release(buf_c); - buf_c = buffer_acquire(dd->local_buffer); + /* handle module runtime unbind */ + if (!dd->local_buffer) { + set_new_local_buffer(dd, dev); + + if (!dd->local_buffer) { + comp_warn(dev, "dai_zephyr_copy(): local buffer unbound, cannot copy"); + return 0; + } + } /* calculate minimum size to copy */ if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + buf_c = buffer_acquire(dd->local_buffer); src_samples = audio_stream_get_avail_samples(&buf_c->stream); sink_samples = free_bytes / sampling; samples = MIN(src_samples, sink_samples); + buffer_release(buf_c); } else { + struct list_item *sink_list; + src_samples = avail_bytes / sampling; - sink_samples = audio_stream_get_free_samples(&buf_c->stream); - samples = MIN(src_samples, sink_samples); + + /* + * there's only one sink buffer in the case of endpoint DAI devices created by + * a DAI copier and it is chosen as the dd->local buffer + */ + if (!converter) { + buf_c = buffer_acquire(dd->local_buffer); + sink_samples = audio_stream_get_free_samples(&buf_c->stream); + samples = MIN(samples, sink_samples); + buffer_release(buf_c); + } else { + /* + * In the case of capture DAI's with multiple sink buffers, compute the + * minimum number of samples based on the DMA avail_bytes and the free + * samples in all active sink buffers. + */ + list_for_item(sink_list, &dev->bsink_list) { + struct comp_dev *sink_dev; + struct comp_buffer *sink; + + sink = container_of(sink_list, struct comp_buffer, source_list); + buf_c = buffer_acquire(sink); + sink_dev = buf_c->sink; + + if (sink_dev && sink_dev->state == COMP_STATE_ACTIVE) { + sink_samples = + audio_stream_get_free_samples(&buf_c->stream); + samples = MIN(samples, sink_samples); + } + buffer_release(buf_c); + } + } + + samples = MIN(samples, src_samples); } /* limit bytes per copy to one period for the whole pipeline @@ -1274,47 +1605,55 @@ static int dai_copy(struct comp_dev *dev) copy_bytes = samples * sampling; - comp_dbg(dev, "dai_copy(), dir: %d copy_bytes= 0x%x, frames= %d", - dev->direction, copy_bytes, - samples / buf_c->stream.channels); - - buffer_release(buf_c); + comp_dbg(dev, "dai_zephyr_copy(), dir: %d copy_bytes= 0x%x", + dev->direction, copy_bytes); /* Check possibility of glitch occurrence */ if (dev->direction == SOF_IPC_STREAM_PLAYBACK && copy_bytes + avail_bytes < dd->period_bytes) - comp_warn(dev, "dai_copy(): Copy_bytes %d + avail bytes %d < period bytes %d, possible glitch", + comp_warn(dev, "dai_zephyr_copy(): Copy_bytes %d + avail bytes %d < period bytes %d, possible glitch", copy_bytes, avail_bytes, dd->period_bytes); else if (dev->direction == SOF_IPC_STREAM_CAPTURE && copy_bytes + free_bytes < dd->period_bytes) - comp_warn(dev, "dai_copy(): Copy_bytes %d + free bytes %d < period bytes %d, possible glitch", + comp_warn(dev, "dai_zephyr_copy(): Copy_bytes %d + free bytes %d < period bytes %d, possible glitch", copy_bytes, free_bytes, dd->period_bytes); /* return if nothing to copy */ if (!copy_bytes) { - comp_warn(dev, "dai_copy(): nothing to copy"); + comp_warn(dev, "dai_zephyr_copy(): nothing to copy"); return 0; } /* trigger optional DAI_TRIGGER_COPY which prepares dai to copy */ ret = dai_trigger(dd->dai->dev, dev->direction, DAI_TRIGGER_COPY); if (ret < 0) - comp_warn(dev, "dai_copy(): dai trigger copy failed"); + comp_warn(dev, "dai_zephyr_copy(): dai trigger copy failed"); - if (dai_dma_cb(dev, copy_bytes) == DMA_CB_STATUS_END) + if (dai_dma_cb(dd, dev, copy_bytes, converter) == DMA_CB_STATUS_END) dma_stop(dd->chan->dma->z_dev, dd->chan->index); ret = dma_reload(dd->chan->dma->z_dev, dd->chan->index, 0, 0, copy_bytes); if (ret < 0) { - dai_report_xrun(dev, copy_bytes); + dai_report_xrun(dd, dev, copy_bytes); return ret; } - dai_dma_position_update(dev); + dai_dma_position_update(dd, dev); return ret; } +static int dai_copy(struct comp_dev *dev) +{ + struct dai_data *dd = comp_get_drvdata(dev); + + /* + * DAI devices will only ever have 1 sink, so no need to pass an array of PCM converter + * functions. The default one to use is set in dd->process. + */ + return dai_zephyr_copy(dd, dev, NULL); +} + /** * \brief Get DAI parameters and configure timestamping * \param[in, out] dev DAI device. @@ -1325,9 +1664,8 @@ static int dai_copy(struct comp_dev *dev) * DAI must be prepared before this function is used (for DMA information). If not, an error * is returned. */ -static int dai_ts_config_op(struct comp_dev *dev) +int dai_zephyr_ts_config_op(struct dai_data *dd, struct comp_dev *dev) { - struct dai_data *dd = comp_get_drvdata(dev); struct ipc_config_dai *dai = &dd->ipc_config; struct dai_ts_cfg cfg; @@ -1361,43 +1699,60 @@ static int dai_ts_config_op(struct comp_dev *dev) return dai_ts_config(dd->dai->dev, &cfg); } -static int dai_ts_start_op(struct comp_dev *dev) +static int dai_ts_config_op(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); - struct dai_ts_cfg cfg; - comp_dbg(dev, "dai_ts_start()"); + return dai_zephyr_ts_config_op(dd, dev); +} + +int dai_zephyr_ts_start(struct dai_data *dd, struct comp_dev *dev) +{ + struct dai_ts_cfg cfg; return dai_ts_start(dd->dai->dev, &cfg); } -static int dai_ts_get_op(struct comp_dev *dev, struct timestamp_data *tsd) +static int dai_ts_start_op(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); + + comp_dbg(dev, "dai_ts_start()"); + return dai_zephyr_ts_start(dd, dev); +} + +int dai_zephyr_ts_get(struct dai_data *dd, struct comp_dev *dev, struct timestamp_data *tsd) +{ struct dai_ts_data tsdata; struct dai_ts_cfg cfg; - int ret; - comp_dbg(dev, "dai_ts_get()"); + /* TODO: convert to timestamp_data */ + return dai_ts_get(dd->dai->dev, &cfg, &tsdata); +} - ret = dai_ts_get(dd->dai->dev, &cfg, &tsdata); +static int dai_ts_get_op(struct comp_dev *dev, struct timestamp_data *tsd) +{ + struct dai_data *dd = comp_get_drvdata(dev); - if (ret < 0) - return ret; + comp_dbg(dev, "dai_ts_get()"); - /* todo convert to timestamp_data */ + return dai_zephyr_ts_get(dd, dev, tsd); +} - return ret; +int dai_zephyr_ts_stop(struct dai_data *dd, struct comp_dev *dev) +{ + struct dai_ts_cfg cfg; + + return dai_ts_stop(dd->dai->dev, &cfg); } static int dai_ts_stop_op(struct comp_dev *dev) { struct dai_data *dd = comp_get_drvdata(dev); - struct dai_ts_cfg cfg; comp_dbg(dev, "dai_ts_stop()"); - return dai_ts_stop(dd->dai->dev, &cfg); + return dai_zephyr_ts_stop(dd, dev); } uint32_t dai_get_init_delay_ms(struct dai *dai) @@ -1432,6 +1787,29 @@ static uint64_t dai_get_processed_data(struct comp_dev *dev, uint32_t stream_no, return ret; } +#ifdef CONFIG_IPC_MAJOR_4 +int dai_zephyr_unbind(struct dai_data *dd, struct comp_dev *dev, void *data) +{ + struct comp_buffer __sparse_cache *local_buf_c; + struct ipc4_module_bind_unbind *bu; + int buf_id; + + bu = (struct ipc4_module_bind_unbind *)data; + buf_id = IPC4_COMP_ID(bu->extension.r.src_queue, bu->extension.r.dst_queue); + + if (dd && dd->local_buffer) { + local_buf_c = buffer_acquire(dd->local_buffer); + if (local_buf_c->id == buf_id) { + comp_dbg(dev, "dai_zephyr_unbind: local_buffer %x unbound", buf_id); + dd->local_buffer = NULL; + } + buffer_release(local_buf_c); + } + + return 0; +} +#endif /* CONFIG_IPC_MAJOR_4 */ + static const struct comp_driver comp_dai = { .type = SOF_COMP_DAI, .uid = SOF_RT_UUID(dai_comp_uuid), diff --git a/src/audio/dcblock/dcblock.c b/src/audio/dcblock/dcblock.c index f6554156f46d..1d33a389dea6 100644 --- a/src/audio/dcblock/dcblock.c +++ b/src/audio/dcblock/dcblock.c @@ -359,15 +359,15 @@ static int dcblock_prepare(struct comp_dev *dev) sink_c = buffer_acquire(sinkb); /* get source data format */ - cd->source_format = source_c->stream.frame_fmt; + cd->source_format = audio_stream_get_frm_fmt(&source_c->stream); /* get sink data format and period bytes */ - cd->sink_format = sink_c->stream.frame_fmt; + cd->sink_format = audio_stream_get_frm_fmt(&sink_c->stream); sink_period_bytes = audio_stream_period_bytes(&sink_c->stream, dev->frames); - if (sink_c->stream.size < sink_period_bytes) { + if (audio_stream_get_size(&sink_c->stream) < sink_period_bytes) { comp_err(dev, "dcblock_prepare(): sink buffer size %d is insufficient < %d", - sink_c->stream.size, sink_period_bytes); + audio_stream_get_size(&sink_c->stream), sink_period_bytes); ret = -ENOMEM; goto out; } diff --git a/src/audio/dcblock/dcblock_generic.c b/src/audio/dcblock/dcblock_generic.c index b821bb7d5821..422668fe8282 100644 --- a/src/audio/dcblock/dcblock_generic.c +++ b/src/audio/dcblock/dcblock_generic.c @@ -42,14 +42,14 @@ static void dcblock_s16_default(const struct comp_dev *dev, { struct comp_data *cd = comp_get_drvdata(dev); struct dcblock_state *state; - int16_t *x = source->r_ptr; - int16_t *y = sink->w_ptr; + int16_t *x = audio_stream_get_rptr(source); + int16_t *y = audio_stream_get_wptr(sink); int32_t R; int32_t tmp; int idx; int ch; int i, n, nmax; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int samples = nch * frames; while (samples) { @@ -83,14 +83,14 @@ static void dcblock_s24_default(const struct comp_dev *dev, { struct comp_data *cd = comp_get_drvdata(dev); struct dcblock_state *state; - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); int32_t R; int32_t tmp; int idx; int ch; int i, n, nmax; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int samples = nch * frames; while (samples) { @@ -124,13 +124,13 @@ static void dcblock_s32_default(const struct comp_dev *dev, { struct comp_data *cd = comp_get_drvdata(dev); struct dcblock_state *state; - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); int32_t R; int idx; int ch; int i, n, nmax; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int samples = nch * frames; while (samples) { diff --git a/src/audio/dcblock/dcblock_hifi3.c b/src/audio/dcblock/dcblock_hifi3.c index df18d6d1a01d..415e0d8704e1 100644 --- a/src/audio/dcblock/dcblock_hifi3.c +++ b/src/audio/dcblock/dcblock_hifi3.c @@ -32,8 +32,8 @@ static inline ae_int32x2 dcblock_cal(ae_int32x2 R, ae_int32x2 state_x, ae_int32 static inline void dcblock_set_circular(const struct audio_stream __sparse_cache *source) { /* Set source as circular buffer 0 */ - AE_SETCBEGIN0(source->addr); - AE_SETCEND0(source->end_addr); + AE_SETCBEGIN0(audio_stream_get_addr(source)); + AE_SETCEND0(audio_stream_get_end_addr(source)); } #if CONFIG_FORMAT_S16LE @@ -43,14 +43,14 @@ static void dcblock_s16_default(const struct comp_dev *dev, uint32_t frames) { struct comp_data *cd = comp_get_drvdata(dev); - ae_int16 *src = (ae_int16 *)source->r_ptr; - ae_int16 *dst = (ae_int16 *)sink->w_ptr; + ae_int16 *src = audio_stream_get_rptr(source); + ae_int16 *dst = audio_stream_get_wptr(sink); ae_int16 *in; ae_int16 *out; ae_int32x2 R, state_x, state_y, sample; ae_int16x4 in_sample, out_sample; int ch, i, n; - int nch = source->channels; + int nch = audio_stream_get_channels(source); const int inc = nch * sizeof(ae_int16); int samples = nch * frames; @@ -91,14 +91,14 @@ static void dcblock_s24_default(const struct comp_dev *dev, uint32_t frames) { struct comp_data *cd = comp_get_drvdata(dev); - ae_int32 *src = (ae_int32 *)source->r_ptr; - ae_int32 *dst = (ae_int32 *)sink->w_ptr; + ae_int32 *src = audio_stream_get_rptr(source); + ae_int32 *dst = audio_stream_get_wptr(sink); ae_int32 *in; ae_int32 *out; ae_int32x2 R, state_x, state_y; ae_int32x2 in_sample, out_sample; int ch, i, n; - int nch = source->channels; + int nch = audio_stream_get_channels(source); const int inc = nch * sizeof(ae_int32); int samples = nch * frames; @@ -139,14 +139,14 @@ static void dcblock_s32_default(const struct comp_dev *dev, uint32_t frames) { struct comp_data *cd = comp_get_drvdata(dev); - ae_int32 *src = (ae_int32 *)source->r_ptr; - ae_int32 *dst = (ae_int32 *)sink->w_ptr; + ae_int32 *src = audio_stream_get_rptr(source); + ae_int32 *dst = audio_stream_get_wptr(sink); ae_int32 *in; ae_int32 *out; ae_int32x2 R, state_x, state_y; ae_int32x2 in_sample; int ch, i, n; - int nch = source->channels; + int nch = audio_stream_get_channels(source); const int inc = nch * sizeof(ae_int32); int samples = nch * frames; diff --git a/src/audio/dcblock/dcblock_hifi4.c b/src/audio/dcblock/dcblock_hifi4.c index 8ba7fb87c1f9..53cab3d98df2 100644 --- a/src/audio/dcblock/dcblock_hifi4.c +++ b/src/audio/dcblock/dcblock_hifi4.c @@ -33,12 +33,12 @@ static inline void dcblock_set_circular(const struct audio_stream __sparse_cache const struct audio_stream __sparse_cache *sink) { /* Set source as circular buffer 0 */ - AE_SETCBEGIN0(source->addr); - AE_SETCEND0(source->end_addr); + AE_SETCBEGIN0(audio_stream_get_addr(source)); + AE_SETCEND0(audio_stream_get_end_addr(source)); /* Set sink as circular buffer 1 */ - AE_SETCBEGIN1(sink->addr); - AE_SETCEND1(sink->end_addr); + AE_SETCBEGIN1(audio_stream_get_addr(sink)); + AE_SETCEND1(audio_stream_get_end_addr(sink)); } #if CONFIG_FORMAT_S16LE @@ -53,13 +53,13 @@ static void dcblock_s16_default(const struct comp_dev *dev, ae_int32x2 R, state_x, state_y, sample; ae_int16x4 in_sample, out_sample; int ch, i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); const int inc = nch * sizeof(ae_int16); dcblock_set_circular(source, sink); for (ch = 0; ch < nch; ch++) { - in = (ae_int16 *)source->r_ptr + ch; - out = (ae_int16 *)sink->w_ptr + ch; + in = (ae_int16 *)audio_stream_get_rptr(source) + ch; + out = (ae_int16 *)audio_stream_get_wptr(sink) + ch; state_x = cd->state[ch].x_prev; state_y = cd->state[ch].y_prev; R = cd->R_coeffs[ch]; @@ -91,13 +91,13 @@ static void dcblock_s24_default(const struct comp_dev *dev, ae_int32x2 R, state_x, state_y; ae_int32x2 in_sample, out_sample; int ch, i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); const int inc = nch * sizeof(ae_int32); dcblock_set_circular(source, sink); for (ch = 0; ch < nch; ch++) { - in = (ae_int32 *)source->r_ptr + ch; - out = (ae_int32 *)sink->w_ptr + ch; + in = (ae_int32 *)audio_stream_get_rptr(source) + ch; + out = (ae_int32 *)audio_stream_get_wptr(sink) + ch; state_x = cd->state[ch].x_prev; state_y = cd->state[ch].y_prev; @@ -130,13 +130,13 @@ static void dcblock_s32_default(const struct comp_dev *dev, ae_int32x2 R, state_x, state_y; ae_int32x2 in_sample; int ch, i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); const int inc = nch * sizeof(ae_int32); dcblock_set_circular(source, sink); for (ch = 0; ch < nch; ch++) { - in = (ae_int32 *)source->r_ptr + ch; - out = (ae_int32 *)sink->w_ptr + ch; + in = (ae_int32 *)audio_stream_get_rptr(source) + ch; + out = (ae_int32 *)audio_stream_get_wptr(sink) + ch; state_x = cd->state[ch].x_prev; state_y = cd->state[ch].y_prev; diff --git a/src/audio/drc/drc.c b/src/audio/drc/drc.c index 41df9ffe0652..6f88054b4990 100644 --- a/src/audio/drc/drc.c +++ b/src/audio/drc/drc.c @@ -344,7 +344,8 @@ static int drc_copy(struct comp_dev *dev) /* Check for changed configuration */ if (comp_is_new_data_blob_available(cd->model_handler)) { cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL); - ret = drc_setup(cd, source_c->stream.channels, source_c->stream.rate); + ret = drc_setup(cd, audio_stream_get_channels(&source_c->stream), + audio_stream_get_rate(&source_c->stream)); if (ret < 0) { comp_err(dev, "drc_copy(), failed DRC setup"); goto out; @@ -391,14 +392,15 @@ static int drc_prepare(struct comp_dev *dev) source_c = buffer_acquire(sourceb); /* get source data format */ - cd->source_format = source_c->stream.frame_fmt; + cd->source_format = audio_stream_get_frm_fmt(&source_c->stream); /* Initialize DRC */ comp_info(dev, "drc_prepare(), source_format=%d, sink_format=%d", cd->source_format, cd->source_format); cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL); if (cd->config) { - ret = drc_setup(cd, source_c->stream.channels, source_c->stream.rate); + ret = drc_setup(cd, audio_stream_get_channels(&source_c->stream), + audio_stream_get_rate(&source_c->stream)); if (ret < 0) { comp_err(dev, "drc_prepare() error: drc_setup failed."); goto out_source; @@ -419,9 +421,9 @@ static int drc_prepare(struct comp_dev *dev) sink_c = buffer_acquire(sinkb); /* validate sink data format and period bytes */ - if (cd->source_format != sink_c->stream.frame_fmt) { + if (cd->source_format != audio_stream_get_frm_fmt(&sink_c->stream)) { comp_err(dev, "drc_prepare(): Source fmt %d and sink fmt %d are different.", - cd->source_format, sink_c->stream.frame_fmt); + cd->source_format, audio_stream_get_frm_fmt(&sink_c->stream)); ret = -EINVAL; goto out_sink; } @@ -429,9 +431,9 @@ static int drc_prepare(struct comp_dev *dev) sink_period_bytes = audio_stream_period_bytes(&sink_c->stream, dev->frames); - if (sink_c->stream.size < sink_period_bytes) { + if (audio_stream_get_size(&sink_c->stream) < sink_period_bytes) { comp_err(dev, "drc_prepare(), sink buffer size %d is insufficient", - sink_c->stream.size); + audio_stream_get_size(&sink_c->stream)); ret = -ENOMEM; } diff --git a/src/audio/drc/drc_generic.c b/src/audio/drc/drc_generic.c index 474d406b1a5f..9d7a2a08048d 100644 --- a/src/audio/drc/drc_generic.c +++ b/src/audio/drc/drc_generic.c @@ -468,7 +468,7 @@ static void drc_process_one_division(struct drc_state *state, void drc_default_pass(const struct comp_dev *dev, const struct audio_stream __sparse_cache *source, struct audio_stream __sparse_cache *sink, uint32_t frames) { - audio_stream_copy(source, 0, sink, 0, frames * source->channels); + 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) @@ -492,7 +492,7 @@ static void drc_delay_input_sample_s16(struct drc_state *state, int16_t *x0 = *x; int16_t *y0 = *y; int remaining_samples = samples; - int nch = source->channels; + int nch = audio_stream_get_channels(source); while (remaining_samples) { nbuf = audio_stream_samples_without_wrap_s16(source, x0); @@ -531,9 +531,9 @@ static void drc_s16_default(const struct comp_dev *dev, struct audio_stream __sparse_cache *sink, uint32_t frames) { - int16_t *x = source->r_ptr; - int16_t *y = sink->w_ptr; - int nch = source->channels; + 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 = comp_get_drvdata(dev); struct drc_state *state = &cd->state; @@ -587,7 +587,7 @@ static void drc_delay_input_sample_s32(struct drc_state *state, int32_t *x0 = *x; int32_t *y0 = *y; int remaining_samples = samples; - int nch = source->channels; + int nch = audio_stream_get_channels(source); while (remaining_samples) { nbuf = audio_stream_samples_without_wrap_s32(source, x0); @@ -638,7 +638,7 @@ static void drc_delay_input_sample_s24(struct drc_state *state, int32_t *x0 = *x; int32_t *y0 = *y; int remaining_samples = samples; - int nch = source->channels; + int nch = audio_stream_get_channels(source); while (remaining_samples) { nbuf = audio_stream_samples_without_wrap_s24(source, x0); @@ -677,9 +677,9 @@ static void drc_s24_default(const struct comp_dev *dev, struct audio_stream __sparse_cache *sink, uint32_t frames) { - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; - int nch = source->channels; + 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 = comp_get_drvdata(dev); struct drc_state *state = &cd->state; @@ -725,9 +725,9 @@ static void drc_s32_default(const struct comp_dev *dev, struct audio_stream __sparse_cache *sink, uint32_t frames) { - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; - int nch = source->channels; + 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 = comp_get_drvdata(dev); struct drc_state *state = &cd->state; diff --git a/src/audio/eq_fir/eq_fir.c b/src/audio/eq_fir/eq_fir.c index 0b293c1ea449..547964eed843 100644 --- a/src/audio/eq_fir/eq_fir.c +++ b/src/audio/eq_fir/eq_fir.c @@ -175,7 +175,7 @@ static int eq_fir_params(struct processing_module *mod) struct comp_dev *dev = mod->dev; struct comp_buffer *sinkb; struct comp_buffer __sparse_cache *sink_c; - uint32_t __sparse_cache valid_fmt, frame_fmt; + enum sof_ipc_frame valid_fmt, frame_fmt; int i, ret; comp_dbg(dev, "eq_fir_params()"); @@ -216,7 +216,7 @@ static void eq_fir_passthrough(struct fir_state_32x16 fir[], struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - audio_stream_copy(source, 0, sink, 0, frames * source->channels); + audio_stream_copy(source, 0, sink, 0, frames * audio_stream_get_channels(source)); } static void eq_fir_free_delaylines(struct comp_data *cd) @@ -523,13 +523,13 @@ static int eq_fir_process(struct processing_module *mod, /* Check for changed configuration */ if (comp_is_new_data_blob_available(cd->model_handler)) { cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL); - ret = eq_fir_setup(mod->dev, cd, source->channels); + ret = eq_fir_setup(mod->dev, cd, audio_stream_get_channels(source)); if (ret < 0) { comp_err(mod->dev, "eq_fir_process(), failed FIR setup"); return ret; } else if (cd->fir_delay_size) { comp_dbg(mod->dev, "eq_fir_process(), active"); - ret = set_fir_func(mod, source->frame_fmt); + ret = set_fir_func(mod, audio_stream_get_frm_fmt(source)); if (ret < 0) return ret; } else { @@ -592,8 +592,8 @@ static int eq_fir_prepare(struct processing_module *mod) source_c = buffer_acquire(sourceb); sink_c = buffer_acquire(sinkb); eq_fir_set_alignment(&source_c->stream, &sink_c->stream); - channels = sink_c->stream.channels; - frame_fmt = source_c->stream.frame_fmt; + channels = audio_stream_get_channels(&sink_c->stream); + frame_fmt = audio_stream_get_frm_fmt(&source_c->stream); buffer_release(sink_c); buffer_release(source_c); diff --git a/src/audio/eq_fir/eq_fir_generic.c b/src/audio/eq_fir/eq_fir_generic.c index 29655cb2004a..ff763d325864 100644 --- a/src/audio/eq_fir/eq_fir_generic.c +++ b/src/audio/eq_fir/eq_fir_generic.c @@ -28,10 +28,10 @@ void eq_fir_s16(struct fir_state_32x16 fir[], struct input_stream_buffer *bsourc struct fir_state_32x16 *filter; int32_t z; int16_t *x0, *y0; - int16_t *x = source->r_ptr; - int16_t *y = sink->w_ptr; + int16_t *x = audio_stream_get_rptr(source); + int16_t *y = audio_stream_get_wptr(sink); int nmax, n, i, j; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; while (remaining_samples) { @@ -66,10 +66,10 @@ void eq_fir_s24(struct fir_state_32x16 fir[], struct input_stream_buffer *bsourc struct fir_state_32x16 *filter; int32_t z; int32_t *x0, *y0; - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); int nmax, n, i, j; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; while (remaining_samples) { @@ -103,10 +103,10 @@ void eq_fir_s32(struct fir_state_32x16 fir[], struct input_stream_buffer *bsourc struct audio_stream __sparse_cache *sink = bsink->data; struct fir_state_32x16 *filter; int32_t *x0, *y0; - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); int nmax, n, i, j; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; while (remaining_samples) { diff --git a/src/audio/eq_fir/eq_fir_hifi2ep.c b/src/audio/eq_fir/eq_fir_hifi2ep.c index 0301f3c0dd6c..29d12587ab1f 100644 --- a/src/audio/eq_fir/eq_fir_hifi2ep.c +++ b/src/audio/eq_fir/eq_fir_hifi2ep.c @@ -31,8 +31,8 @@ void eq_fir_2x_s32(struct fir_state_32x16 fir[], struct input_stream_buffer *bso struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; struct fir_state_32x16 *f; - int32_t *src = (int32_t *)source->r_ptr; - int32_t *snk = (int32_t *)sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *snk = audio_stream_get_wptr(sink); int32_t *x0; int32_t *y0; int32_t *x1; @@ -41,7 +41,7 @@ void eq_fir_2x_s32(struct fir_state_32x16 fir[], struct input_stream_buffer *bso int i; int rshift; int lshift; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int inc = nch << 1; for (ch = 0; ch < nch; ch++) { @@ -75,8 +75,8 @@ void eq_fir_2x_s24(struct fir_state_32x16 fir[], struct input_stream_buffer *bso struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; struct fir_state_32x16 *f; - int32_t *src = (int32_t *)source->r_ptr; - int32_t *snk = (int32_t *)sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *snk = audio_stream_get_wptr(sink); int32_t *x0; int32_t *y0; int32_t *x1; @@ -87,7 +87,7 @@ void eq_fir_2x_s24(struct fir_state_32x16 fir[], struct input_stream_buffer *bso int i; int rshift; int lshift; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int inc = nch << 1; for (ch = 0; ch < nch; ch++) { @@ -123,8 +123,8 @@ void eq_fir_2x_s16(struct fir_state_32x16 fir[], struct input_stream_buffer *bso struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; struct fir_state_32x16 *f; - int16_t *src = (int16_t *)source->r_ptr; - int16_t *snk = (int16_t *)sink->w_ptr; + int16_t *src = audio_stream_get_rptr(source); + int16_t *snk = audio_stream_get_wptr(sink); int16_t *x0; int16_t *y0; int16_t *x1; @@ -135,7 +135,7 @@ void eq_fir_2x_s16(struct fir_state_32x16 fir[], struct input_stream_buffer *bso int i; int rshift; int lshift; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int inc = nch << 1; for (ch = 0; ch < nch; ch++) { diff --git a/src/audio/eq_fir/eq_fir_hifi3.c b/src/audio/eq_fir/eq_fir_hifi3.c index 94d0a8c0a5de..b9b5f3b1ec63 100644 --- a/src/audio/eq_fir/eq_fir_hifi3.c +++ b/src/audio/eq_fir/eq_fir_hifi3.c @@ -32,56 +32,50 @@ void eq_fir_2x_s32(struct fir_state_32x16 fir[], struct input_stream_buffer *bso struct fir_state_32x16 *f; ae_int32x2 d0 = 0; ae_int32x2 d1 = 0; - ae_int32 *src = (ae_int32 *)source->r_ptr; - ae_int32 *snk = (ae_int32 *)sink->w_ptr; + ae_int32 *src = audio_stream_get_rptr(source); + ae_int32 *dst = audio_stream_get_wptr(sink); ae_int32 *x; ae_int32 *y0; ae_int32 *y1; int ch; - int i; + int i, n, nmax; int rshift; int lshift; int shift; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int inc_nch_s = nch * sizeof(int32_t); int inc_2nch_s = 2 * inc_nch_s; - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts. - */ - f = &fir[ch]; - fir_get_lrshifts(f, &lshift, &rshift); - shift = lshift - rshift; - - /* Copy src to x and advance src with dummy load */ - fir_comp_setup_circular(source); - x = src; - AE_L32_XC(d0, src, sizeof(int32_t)); - - /* Copy snk to y0 and advance snk with dummy load. Pointer - * y1 is set to be ahead of y0 with one frame. - */ - fir_comp_setup_circular(sink); - y0 = snk; - y1 = snk; - AE_L32_XC(d0, snk, sizeof(int32_t)); - AE_L32_XC(d1, y1, inc_nch_s); - - for (i = 0; i < (frames >> 1); i++) { - /* Load two input samples via input pointer x */ - fir_comp_setup_circular(source); - AE_L32_XC(d0, x, inc_nch_s); - AE_L32_XC(d1, x, inc_nch_s); - - /* Compute FIR */ + int samples = nch * frames; + + while (samples) { + nmax = audio_stream_samples_without_wrap_s32(sink, dst); + n = MIN(nmax, samples); + nmax = audio_stream_samples_without_wrap_s32(source, src); + n = MIN(n, nmax); + for (ch = 0; ch < nch; ch++) { + /* Get FIR instance and get shifts.*/ + f = &fir[ch]; + fir_get_lrshifts(f, &lshift, &rshift); + shift = lshift - rshift; + /* set f->delay as circular buffer */ fir_core_setup_circular(f); - fir_32x16_2x_hifi3(f, d0, d1, y0, y1, shift); - /* Update output pointers y0 and y1 with dummy loads */ - fir_comp_setup_circular(sink); - AE_L32_XC(d0, y0, inc_2nch_s); - AE_L32_XC(d1, y1, inc_2nch_s); + x = src + ch; + y0 = dst + ch; + y1 = y0 + nch; + + for (i = 0; i < (n >> 1); i += nch) { + /* Load two input samples via input pointer x */ + AE_L32_XP(d0, x, inc_nch_s); + AE_L32_XP(d1, x, inc_nch_s); + fir_32x16_2x_hifi3(f, d0, d1, y0, y1, shift); + AE_L32_XC(d0, y0, inc_2nch_s); + AE_L32_XC(d1, y1, inc_2nch_s); + } } + samples -= n; + dst = audio_stream_wrap(sink, dst + n); + src = audio_stream_wrap(source, src + n); } } #endif /* CONFIG_FORMAT_S32LE */ @@ -97,65 +91,63 @@ void eq_fir_2x_s24(struct fir_state_32x16 fir[], struct input_stream_buffer *bso ae_int32x2 d1 = 0; ae_int32 z0; ae_int32 z1; - ae_int32 *src = (ae_int32 *)source->r_ptr; - ae_int32 *snk = (ae_int32 *)sink->w_ptr; + ae_int32 *src = audio_stream_get_rptr(source); + ae_int32 *dst = audio_stream_get_wptr(sink); ae_int32 *x; ae_int32 *y; int ch; - int i; + int i, n, nmax; int rshift; int lshift; int shift; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int inc_nch_s = nch * sizeof(int32_t); - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts. - */ - f = &fir[ch]; - fir_get_lrshifts(f, &lshift, &rshift); - shift = lshift - rshift; - - /* Copy src to x and advance src with dummy load */ - fir_comp_setup_circular(source); - x = src; - AE_L32_XC(d0, src, sizeof(int32_t)); - - /* Copy snk to y0 and advance snk with dummy load. Pointer - * y1 is set to be ahead of y0 with one frame. - */ - fir_comp_setup_circular(sink); - y = snk; - AE_L32_XC(d0, snk, sizeof(int32_t)); - - for (i = 0; i < (frames >> 1); i++) { - /* Load two input samples via input pointer x */ - fir_comp_setup_circular(source); - AE_L32_XC(d0, x, inc_nch_s); - AE_L32_XC(d1, x, inc_nch_s); - - /* Convert Q1.23 to Q1.31 compatible format */ - d0 = AE_SLAA32(d0, 8); - d1 = AE_SLAA32(d1, 8); - - /* Compute FIR */ + int samples = nch * frames; + + while (samples) { + nmax = audio_stream_samples_without_wrap_s24(sink, dst); + n = MIN(nmax, samples); + nmax = audio_stream_samples_without_wrap_s24(source, src); + n = MIN(n, nmax); + for (ch = 0; ch < nch; ch++) { + /* Get FIR instance and get shifts.*/ + f = &fir[ch]; + fir_get_lrshifts(f, &lshift, &rshift); + shift = lshift - rshift; + /* set f->delay as circular buffer */ fir_core_setup_circular(f); - fir_32x16_2x_hifi3(f, d0, d1, &z0, &z1, shift); - /* Shift and round to Q1.23 format */ - d0 = AE_SRAI32R(z0, 8); - d0 = AE_SLAI32S(d0, 8); - d0 = AE_SRAI32(d0, 8); + x = src + ch; + y = dst + ch; + + for (i = 0; i < (n >> 1); i += nch) { + /* Load two input samples via input pointer x */ + AE_L32_XP(d0, x, inc_nch_s); + AE_L32_XP(d1, x, inc_nch_s); + + /* Convert Q1.23 to Q1.31 compatible format */ + d0 = AE_SLAA32(d0, 8); + d1 = AE_SLAA32(d1, 8); + + fir_32x16_2x_hifi3(f, d0, d1, &z0, &z1, shift); + + /* Shift and round to Q1.23 format */ + d0 = AE_SRAI32R(z0, 8); + d0 = AE_SLAI32S(d0, 8); + d0 = AE_SRAI32(d0, 8); - d1 = AE_SRAI32R(z1, 8); - d1 = AE_SLAI32S(d1, 8); - d1 = AE_SRAI32(d1, 8); + d1 = AE_SRAI32R(z1, 8); + d1 = AE_SLAI32S(d1, 8); + d1 = AE_SRAI32(d1, 8); - /* Store output and update output pointers */ - fir_comp_setup_circular(sink); - AE_S32_L_XC(d0, y, inc_nch_s); - AE_S32_L_XC(d1, y, inc_nch_s); + /* Store output and update output pointers */ + AE_S32_L_XC(d0, y, inc_nch_s); + AE_S32_L_XC(d1, y, inc_nch_s); + } } + samples -= n; + dst = audio_stream_wrap(sink, dst + n); + src = audio_stream_wrap(source, src + n); } } #endif /* CONFIG_FORMAT_S24LE */ @@ -173,62 +165,58 @@ void eq_fir_2x_s16(struct fir_state_32x16 fir[], struct input_stream_buffer *bso ae_int32 z1; ae_int32 x0; ae_int32 x1; - ae_int16 *src = (ae_int16 *)source->r_ptr; - ae_int16 *snk = (ae_int16 *)sink->w_ptr; + ae_int16 *src = audio_stream_get_rptr(source); + ae_int16 *dst = audio_stream_get_wptr(sink); ae_int16 *x; ae_int16 *y; int ch; - int i; + int i, n, nmax; int rshift; int lshift; int shift; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int inc_nch_s = nch * sizeof(int16_t); - - for (ch = 0; ch < nch; ch++) { - /* Get FIR instance and get shifts. - */ - f = &fir[ch]; - fir_get_lrshifts(f, &lshift, &rshift); - shift = lshift - rshift; - - /* Copy src to x and advance src to next channel with - * dummy load. - */ - fir_comp_setup_circular(source); - x = src; - AE_L16_XC(d0, src, sizeof(int16_t)); - - /* Copy pointer snk to y0 and advance snk with dummy load. - * Pointer y1 is set to be ahead of y0 with one frame. - */ - fir_comp_setup_circular(sink); - y = snk; - AE_L16_XC(d0, snk, sizeof(int16_t)); - - for (i = 0; i < (frames >> 1); i++) { - /* Load two input samples via input pointer x */ - fir_comp_setup_circular(source); - AE_L16_XC(d0, x, inc_nch_s); - AE_L16_XC(d1, x, inc_nch_s); - - /* Convert Q1.15 to Q1.31 compatible format */ - x0 = AE_CVT32X2F16_32(d0); - x1 = AE_CVT32X2F16_32(d1); - - /* Compute FIR */ + int samples = nch * frames; + + while (samples) { + nmax = audio_stream_samples_without_wrap_s16(sink, dst); + n = MIN(nmax, samples); + nmax = audio_stream_samples_without_wrap_s16(source, src); + n = MIN(n, nmax); + for (ch = 0; ch < nch; ch++) { + /* Get FIR instance and get shifts.*/ + f = &fir[ch]; + fir_get_lrshifts(f, &lshift, &rshift); + shift = lshift - rshift; + /* set f->delay as circular buffer */ fir_core_setup_circular(f); - fir_32x16_2x_hifi3(f, x0, x1, &z0, &z1, shift); - /* Round to Q1.15 format */ - d0 = AE_ROUND16X4F32SSYM(z0, z0); - d1 = AE_ROUND16X4F32SSYM(z1, z1); + x = src + ch; + y = dst + ch; + + for (i = 0; i < (n >> 1); i += nch) { + /* Load two input samples via input pointer x */ + AE_L16_XP(d0, x, inc_nch_s); + AE_L16_XP(d1, x, inc_nch_s); + + /* Convert Q1.15 to Q1.31 compatible format */ + x0 = AE_CVT32X2F16_32(d0); + x1 = AE_CVT32X2F16_32(d1); + + fir_32x16_2x_hifi3(f, x0, x1, &z0, &z1, shift); + + /* Round to Q1.15 format */ + d0 = AE_ROUND16X4F32SSYM(z0, z0); + d1 = AE_ROUND16X4F32SSYM(z1, z1); - /* Store output and update output pointers */ - fir_comp_setup_circular(sink); - AE_S16_0_XC(d0, y, inc_nch_s); - AE_S16_0_XC(d1, y, inc_nch_s); + /* Store output and update output pointers */ + AE_S16_0_XC(d0, y, inc_nch_s); + AE_S16_0_XC(d1, y, inc_nch_s); + } } + samples -= n; + dst = audio_stream_wrap(sink, dst + n); + src = audio_stream_wrap(source, src + n); } } #endif /* CONFIG_FORMAT_S16LE */ diff --git a/src/audio/eq_iir/eq_iir.c b/src/audio/eq_iir/eq_iir.c index 59207c90c6bc..f6673ee162c7 100644 --- a/src/audio/eq_iir/eq_iir.c +++ b/src/audio/eq_iir/eq_iir.c @@ -77,12 +77,12 @@ static void eq_iir_s16_default(struct processing_module *mod, struct input_strea int i; int j; int n; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); const int samples = frames * nch; int processed = 0; - x = source->r_ptr; - y = sink->w_ptr; + x = audio_stream_get_rptr(source); + y = audio_stream_get_wptr(sink); while (processed < samples) { nmax = samples - processed; n1 = audio_stream_bytes_without_wrap(source, x) >> 1; @@ -125,12 +125,12 @@ static void eq_iir_s24_default(struct processing_module *mod, struct input_strea int i; int j; int n; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); const int samples = frames * nch; int processed = 0; - x = source->r_ptr; - y = sink->w_ptr; + x = audio_stream_get_rptr(source); + y = audio_stream_get_wptr(sink); while (processed < samples) { nmax = samples - processed; n1 = audio_stream_bytes_without_wrap(source, x) >> 2; @@ -173,12 +173,12 @@ static void eq_iir_s32_default(struct processing_module *mod, struct input_strea int i; int j; int n; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); const int samples = frames * nch; int processed = 0; - x = source->r_ptr; - y = sink->w_ptr; + x = audio_stream_get_rptr(source); + y = audio_stream_get_wptr(sink); while (processed < samples) { nmax = samples - processed; n1 = audio_stream_bytes_without_wrap(source, x) >> 2; @@ -222,12 +222,12 @@ static void eq_iir_s32_16_default(struct processing_module *mod, int i; int j; int n; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); const int samples = frames * nch; int processed = 0; - x = source->r_ptr; - y = sink->w_ptr; + x = audio_stream_get_rptr(source); + y = audio_stream_get_wptr(sink); while (processed < samples) { nmax = samples - processed; n1 = audio_stream_bytes_without_wrap(source, x) >> 2; /* divide 4 */ @@ -270,12 +270,12 @@ static void eq_iir_s32_24_default(struct processing_module *mod, int i; int j; int n; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); const int samples = frames * nch; int processed = 0; - x = source->r_ptr; - y = sink->w_ptr; + x = audio_stream_get_rptr(source); + y = audio_stream_get_wptr(sink); while (processed < samples) { nmax = samples - processed; n1 = audio_stream_bytes_without_wrap(source, x) >> 2; @@ -306,7 +306,7 @@ static void eq_iir_pass(struct processing_module *mod, struct input_stream_buffe struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - audio_stream_copy(source, 0, sink, 0, frames * source->channels); + audio_stream_copy(source, 0, sink, 0, frames * audio_stream_get_channels(source)); } #if CONFIG_IPC_MAJOR_3 @@ -316,12 +316,12 @@ static void eq_iir_s32_s16_pass(struct processing_module *mod, struct input_stre { struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - int32_t *x = source->r_ptr; - int16_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int16_t *y = audio_stream_get_wptr(sink); int nmax; int n; int i; - int remaining_samples = frames * source->channels; + int remaining_samples = frames * audio_stream_get_channels(source); while (remaining_samples) { nmax = EQ_IIR_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(source, x)); @@ -346,12 +346,12 @@ static void eq_iir_s32_s24_pass(struct processing_module *mod, struct input_stre { struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); int nmax; int n; int i; - int remaining_samples = frames * source->channels; + int remaining_samples = frames * audio_stream_get_channels(source); while (remaining_samples) { nmax = EQ_IIR_BYTES_TO_S32_SAMPLES(audio_stream_bytes_without_wrap(source, x)); @@ -720,8 +720,8 @@ static int eq_iir_verify_params(struct comp_dev *dev, * pcm frame_fmt and will not make any conversion (sink and source * frame_fmt will be equal). */ - buffer_flag = eq_iir_find_func(source_c->stream.frame_fmt, - sink_c->stream.frame_fmt, fm_configured, + buffer_flag = eq_iir_find_func(audio_stream_get_frm_fmt(&source_c->stream), + audio_stream_get_frm_fmt(&sink_c->stream), fm_configured, ARRAY_SIZE(fm_configured)) ? BUFF_PARAMS_FRAME_FMT : 0; @@ -808,8 +808,9 @@ static int eq_iir_process(struct processing_module *mod, /* Check for changed configuration */ if (comp_is_new_data_blob_available(cd->model_handler)) { cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL); - ret = eq_iir_new_blob(mod, cd, source->frame_fmt, - sink->frame_fmt, source->channels); + ret = eq_iir_new_blob(mod, cd, audio_stream_get_frm_fmt(source), + audio_stream_get_frm_fmt(sink), + audio_stream_get_channels(source)); if (ret) return ret; } @@ -844,7 +845,7 @@ static int eq_iir_params(struct processing_module *mod) struct comp_dev *dev = mod->dev; struct comp_buffer *sinkb; struct comp_buffer __sparse_cache *sink_c; - uint32_t __sparse_cache valid_fmt, frame_fmt; + enum sof_ipc_frame valid_fmt, frame_fmt; int i, ret; comp_dbg(dev, "eq_iir_params()"); @@ -918,9 +919,9 @@ static int eq_iir_prepare(struct processing_module *mod) eq_iir_set_alignment(&source_c->stream, &sink_c->stream); /* get source and sink data format */ - channels = sink_c->stream.channels; - source_format = source_c->stream.frame_fmt; - sink_format = sink_c->stream.frame_fmt; + channels = audio_stream_get_channels(&sink_c->stream); + source_format = audio_stream_get_frm_fmt(&source_c->stream); + sink_format = audio_stream_get_frm_fmt(&sink_c->stream); buffer_release(sink_c); buffer_release(source_c); diff --git a/src/audio/google/google_hotword_detect.c b/src/audio/google/google_hotword_detect.c index 45cb708c6cec..8faad2180e02 100644 --- a/src/audio/google/google_hotword_detect.c +++ b/src/audio/google/google_hotword_detect.c @@ -181,7 +181,7 @@ static int ghd_params(struct comp_dev *dev, if (source_c->stream.channels != 1) { comp_err(dev, "ghd_params(): Only single-channel supported"); ret = -EINVAL; - } else if (source_c->stream.frame_fmt != SOF_IPC_FRAME_S16_LE) { + } else if (audio_stream_get_frm_fmt(&source_c->stream) != SOF_IPC_FRAME_S16_LE) { comp_err(dev, "ghd_params(): Only S16_LE supported"); ret = -EINVAL; } else if (source_c->stream.rate != KPB_SAMPLNG_FREQUENCY) { @@ -406,23 +406,24 @@ static int ghd_copy(struct comp_dev *dev) comp_dbg(dev, "ghd_copy() avail_bytes %u", bytes); comp_dbg(dev, "buffer begin/r_ptr/end [0x%x 0x%x 0x%x]", - (uint32_t)stream->addr, - (uint32_t)stream->r_ptr, - (uint32_t)stream->end_addr); + (uint32_t)audio_stream_get_addr(stream), + (uint32_t)audio_stream_get_rptr(stream), + (uint32_t)audio_stream_get_end_addr(stream)); /* copy and perform detection */ buffer_stream_invalidate(source_c, bytes); - tail_bytes = (char *)stream->end_addr - (char *)stream->r_ptr; + tail_bytes = (char *)audio_stream_get_end_addr(stream) - + (char *)audio_stream_get_rptr(stream); if (bytes <= tail_bytes) tail_bytes = bytes; else head_bytes = bytes - tail_bytes; if (tail_bytes) - ghd_detect(dev, stream, stream->r_ptr, tail_bytes); + ghd_detect(dev, stream, audio_stream_get_rptr(stream), tail_bytes); if (head_bytes) - ghd_detect(dev, stream, stream->addr, head_bytes); + ghd_detect(dev, stream, audio_stream_get_addr(stream), head_bytes); /* calc new available */ comp_update_buffer_consume(source_c, bytes); diff --git a/src/audio/google/google_rtc_audio_processing.c b/src/audio/google/google_rtc_audio_processing.c index f6a893b6d6dc..355797078406 100644 --- a/src/audio/google/google_rtc_audio_processing.c +++ b/src/audio/google/google_rtc_audio_processing.c @@ -105,20 +105,23 @@ static int google_rtc_audio_processing_params( /* update sink format */ if (!list_is_empty(&dev->bsink_list)) { struct ipc4_audio_format *out_fmt = &cd->config.output_fmt; + enum sof_ipc_frame valid_fmt, frame_fmt; sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); sink_c = buffer_acquire(sink); - sink_c->stream.channels = cd->config.output_fmt.channels_count; - sink_c->stream.rate = cd->config.output_fmt.sampling_frequency; audio_stream_fmt_conversion(out_fmt->depth, out_fmt->valid_bit_depth, - &sink_c->stream.frame_fmt, - &sink_c->stream.valid_sample_fmt, + &frame_fmt, &valid_fmt, out_fmt->s_type); + audio_stream_set_frm_fmt(&sink_c->stream, frame_fmt); + audio_stream_set_valid_fmt(&sink_c->stream, valid_fmt); + audio_stream_set_channels(&sink_c->stream, cd->config.output_fmt.channels_count); + audio_stream_set_rate(&sink_c->stream, cd->config.output_fmt.sampling_frequency); + sink_c->buffer_fmt = out_fmt->interleaving_style; - params->frame_fmt = sink_c->stream.frame_fmt; + params->frame_fmt = frame_fmt; sink_c->hw_params_configured = true; @@ -532,7 +535,7 @@ static int google_rtc_audio_processing_prepare(struct comp_dev *dev) if (source_c->source->pipeline->pipeline_id != dev->pipeline->pipeline_id) { #endif cd->aec_reference = source; - aec_channels = source_c->stream.channels; + aec_channels = audio_stream_get_channels(&source_c->stream); } else { cd->raw_microphone = source; } @@ -552,20 +555,20 @@ static int google_rtc_audio_processing_prepare(struct comp_dev *dev) } output_c = buffer_acquire(cd->output); - frame_fmt = output_c->stream.frame_fmt; - rate = output_c->stream.rate; + frame_fmt = audio_stream_get_frm_fmt(&output_c->stream); + rate = audio_stream_get_rate(&output_c->stream); buffer_release(output_c); - if (cd->num_capture_channels > cd->raw_microphone->stream.channels) { + if (cd->num_capture_channels > audio_stream_get_channels(&cd->raw_microphone->stream)) { comp_err(dev, "unsupported number of microphone channels: %d", - cd->raw_microphone->stream.channels); + audio_stream_get_channels(&cd->raw_microphone->stream)); return -EINVAL; } - if (cd->num_capture_channels > cd->output->stream.channels) { + if (cd->num_capture_channels > audio_stream_get_channels(&cd->output->stream)) { comp_err(dev, "unsupported number of output channels: %d", - cd->output->stream.channels); + audio_stream_get_channels(&cd->output->stream)); return -EINVAL; } @@ -624,14 +627,15 @@ static int google_rtc_audio_processing_copy(struct comp_dev *dev) buffer_c = buffer_acquire(cd->aec_reference); - ref = buffer_c->stream.r_ptr; + ref = audio_stream_get_rptr(&buffer_c->stream); num_aec_reference_frames = audio_stream_get_avail_frames(&buffer_c->stream); num_aec_reference_bytes = audio_stream_get_avail_bytes(&buffer_c->stream); buffer_stream_invalidate(buffer_c, num_aec_reference_bytes); - num_samples_remaining = num_aec_reference_frames * buffer_c->stream.channels; + num_samples_remaining = num_aec_reference_frames * + audio_stream_get_channels(&buffer_c->stream); while (num_samples_remaining) { nmax = audio_stream_samples_without_wrap_s16(&buffer_c->stream, ref); n = MIN(num_samples_remaining, nmax); @@ -640,7 +644,7 @@ static int google_rtc_audio_processing_copy(struct comp_dev *dev) for (channel = 0; channel < cd->num_aec_reference_channels; ++channel) cd->aec_reference_buffer[j++] = ref[channel]; - ref += buffer_c->stream.channels; + ref += audio_stream_get_channels(&buffer_c->stream); ++cd->aec_reference_frame_index; if (cd->aec_reference_frame_index == cd->num_frames) { @@ -659,8 +663,8 @@ static int google_rtc_audio_processing_copy(struct comp_dev *dev) mic_buf = buffer_acquire(cd->raw_microphone); output_buf = buffer_acquire(cd->output); - src = mic_buf->stream.r_ptr; - dst = output_buf->stream.w_ptr; + src = audio_stream_get_rptr(&mic_buf->stream); + dst = audio_stream_get_wptr(&output_buf->stream); comp_get_copy_limits(mic_buf, output_buf, &cl); buffer_stream_invalidate(mic_buf, cl.source_bytes); @@ -695,8 +699,8 @@ static int google_rtc_audio_processing_copy(struct comp_dev *dev) cd->raw_mic_buffer_frame_index = 0; } - src += mic_buf->stream.channels; - dst += output_buf->stream.channels; + src += audio_stream_get_channels(&mic_buf->stream); + dst += audio_stream_get_channels(&output_buf->stream); } num_frames_remaining -= n; src = audio_stream_wrap(&mic_buf->stream, src); diff --git a/src/audio/host-legacy.c b/src/audio/host-legacy.c index 0e500403fd1b..d0efc8a1fb30 100644 --- a/src/audio/host-legacy.c +++ b/src/audio/host-legacy.c @@ -5,6 +5,7 @@ // Author: Liam Girdwood // Keyon Jie +#include #include #include #include @@ -43,72 +44,6 @@ DECLARE_SOF_RT_UUID("host", host_uuid, 0x8b9d100c, 0x6d78, 0x418f, DECLARE_TR_CTX(host_tr, SOF_UUID(host_uuid), LOG_LEVEL_INFO); -/** \brief Host copy function interface. */ -typedef int (*host_copy_func)(struct comp_dev *dev); - -/** - * \brief Host buffer info. - */ -struct hc_buf { - struct dma_sg_elem_array elem_array; /**< array of SG elements */ - uint32_t current; /**< index of current element */ - uint32_t current_end; -}; - -/** - * \brief Host component data. - * - * Host reports local position in the host buffer every params.host_period_bytes - * if the latter is != 0. report_pos is used to track progress since the last - * multiple of host_period_bytes. - * - * host_size is the host buffer size (in bytes) specified in the IPC parameters. - */ -struct host_data { - /* local DMA config */ - struct dma *dma; - struct dma_chan_data *chan; - struct dma_sg_config config; - struct comp_buffer *dma_buffer; - struct comp_buffer *local_buffer; - - /* host position reporting related */ - uint32_t host_size; /**< Host buffer size (in bytes) */ - uint32_t report_pos; /**< Position in current report period */ - uint32_t local_pos; /**< Local position in host buffer */ - uint32_t host_period_bytes; - uint16_t stream_tag; - uint16_t no_stream_position; /**< 1 means don't send stream position */ - uint64_t total_data_processed; - uint8_t cont_update_posn; /**< 1 means continuous update stream position */ - - /* host component attributes */ - enum comp_copy_type copy_type; /**< Current host copy type */ - - /* local and host DMA buffer info */ - struct hc_buf host; - struct hc_buf local; - - /* pointers set during params to host or local above */ - struct hc_buf *source; - struct hc_buf *sink; - - uint32_t dma_copy_align; /**< Minimal chunk of data possible to be - * copied by dma connected to host - */ - uint32_t period_bytes; /**< number of bytes per one period */ - - host_copy_func copy; /**< host copy function */ - pcm_converter_func process; /**< processing function */ - - /* IPC host init info */ - struct ipc_config_host ipc_host; - - /* stream info */ - struct sof_ipc_stream_posn posn; /* TODO: update this */ - struct ipc_msg *msg; /**< host notification */ -}; - static inline struct dma_sg_elem *next_buffer(struct hc_buf *hc) { if (!hc->elem_array.elems || !hc->elem_array.count) @@ -138,9 +73,8 @@ static uint32_t host_dma_get_split(struct host_data *hd, uint32_t bytes) #if CONFIG_FORCE_DMA_COPY_WHOLE_BLOCK -static int host_dma_set_config_and_copy(struct comp_dev *dev, uint32_t bytes) +static int host_dma_set_config_and_copy(struct host_data *hd, struct comp_dev *dev, uint32_t bytes) { - struct host_data *hd = comp_get_drvdata(dev); struct dma_sg_elem *local_elem = hd->config.elem_array.elems; int ret = 0; @@ -169,9 +103,8 @@ static int host_dma_set_config_and_copy(struct comp_dev *dev, uint32_t bytes) * @param dev Host component device. * @return Bytes to be copied. */ -static uint32_t host_get_copy_bytes_one_shot(struct comp_dev *dev) +static uint32_t host_get_copy_bytes_one_shot(struct host_data *hd, struct comp_dev *dev) { - struct host_data *hd = comp_get_drvdata(dev); struct comp_buffer __sparse_cache *buffer_c = buffer_acquire(hd->local_buffer); uint32_t copy_bytes; @@ -195,16 +128,15 @@ static uint32_t host_get_copy_bytes_one_shot(struct comp_dev *dev) * @param dev Host component device. * @return 0 if succeeded, error code otherwise. */ -static int host_copy_one_shot(struct comp_dev *dev) +static int host_copy_one_shot(struct host_data *hd, struct comp_dev *dev, copy_callback_t cb) { - struct host_data *hd = comp_get_drvdata(dev); uint32_t copy_bytes = 0; uint32_t split_value = 0; int ret = 0; comp_dbg(dev, "host_copy_one_shot()"); - copy_bytes = host_get_copy_bytes_one_shot(dev); + copy_bytes = host_get_copy_bytes_one_shot(hd, dev); if (!copy_bytes) { comp_info(dev, "host_copy_one_shot(): no bytes to copy"); return ret; @@ -215,7 +147,7 @@ static int host_copy_one_shot(struct comp_dev *dev) split_value = host_dma_get_split(hd, copy_bytes); copy_bytes -= split_value; - ret = host_dma_set_config_and_copy(dev, copy_bytes); + ret = host_dma_set_config_and_copy(hd, dev, copy_bytes); if (ret < 0) return ret; @@ -233,9 +165,8 @@ static int host_copy_one_shot(struct comp_dev *dev) * @param dev Host component device. * @return Bytes to be copied. */ -static uint32_t host_get_copy_bytes_one_shot(struct comp_dev *dev) +static uint32_t host_get_copy_bytes_one_shot(struct host_data *hd, struct comp_dev *dev) { - struct host_data *hd = comp_get_drvdata(dev); struct dma_sg_elem *local_elem = hd->config.elem_array.elems; struct comp_buffer __sparse_cache *buffer_c = buffer_acquire(hd->local_buffer); uint32_t copy_bytes; @@ -269,15 +200,14 @@ static uint32_t host_get_copy_bytes_one_shot(struct comp_dev *dev) * @param dev Host component device. * @return 0 if succeeded, error code otherwise. */ -static int host_copy_one_shot(struct comp_dev *dev) +static int host_copy_one_shot(struct host_data *hd, struct comp_dev *dev, copy_callback_t cb) { - struct host_data *hd = comp_get_drvdata(dev); uint32_t copy_bytes = 0; int ret = 0; comp_dbg(dev, "host_copy_one_shot()"); - copy_bytes = host_get_copy_bytes_one_shot(dev); + copy_bytes = host_get_copy_bytes_one_shot(hd, dev); if (!copy_bytes) { comp_info(dev, "host_copy_one_shot(): no bytes to copy"); return ret; @@ -300,9 +230,8 @@ static int host_copy_one_shot(struct comp_dev *dev) } #endif -static void host_update_position(struct comp_dev *dev, uint32_t bytes) +void host_update_position(struct host_data *hd, struct comp_dev *dev, uint32_t bytes) { - struct host_data *hd = comp_get_drvdata(dev); struct comp_buffer __sparse_cache *source; struct comp_buffer __sparse_cache *sink; int ret; @@ -385,9 +314,8 @@ static void host_update_position(struct comp_dev *dev, uint32_t bytes) * This means we must check we do not overflow host period/buffer/page * boundaries on each transfer and split the DMA transfer if we do overflow. */ -static void host_one_shot_cb(struct comp_dev *dev, uint32_t bytes) +void host_one_shot_cb(struct host_data *hd, uint32_t bytes) { - struct host_data *hd = comp_get_drvdata(dev); struct dma_sg_elem *local_elem = hd->config.elem_array.elems; struct dma_sg_elem *source_elem; struct dma_sg_elem *sink_elem; @@ -427,14 +355,14 @@ static void host_dma_cb(void *arg, enum notify_id type, void *data) struct host_data *hd = comp_get_drvdata(dev); uint32_t bytes = next->elem.size; - comp_cl_dbg(&comp_host, "host_dma_cb() %p", &comp_host); + comp_dbg(dev, "host_dma_cb() %p", &comp_host); /* update position */ - host_update_position(dev, bytes); + host_update_position(hd, dev, bytes); /* callback for one shot copy */ if (hd->copy_type == COMP_COPY_ONE_SHOT) - host_one_shot_cb(dev, bytes); + host_one_shot_cb(hd, bytes); } /** @@ -442,9 +370,8 @@ static void host_dma_cb(void *arg, enum notify_id type, void *data) * @param dev Host component device. * @return Bytes to be copied. */ -static uint32_t host_get_copy_bytes_normal(struct comp_dev *dev) +static uint32_t host_get_copy_bytes_normal(struct host_data *hd, struct comp_dev *dev) { - struct host_data *hd = comp_get_drvdata(dev); struct comp_buffer __sparse_cache *buffer_c; uint32_t avail_bytes = 0; uint32_t free_bytes = 0; @@ -494,9 +421,8 @@ static uint32_t host_get_copy_bytes_normal(struct comp_dev *dev) * @param dev Host component device. * @return 0 if succeeded, error code otherwise. */ -static int host_copy_normal(struct comp_dev *dev) +static int host_copy_normal(struct host_data *hd, struct comp_dev *dev, copy_callback_t cb) { - struct host_data *hd = comp_get_drvdata(dev); uint32_t copy_bytes = 0; uint32_t flags = 0; int ret; @@ -506,7 +432,7 @@ static int host_copy_normal(struct comp_dev *dev) if (hd->copy_type == COMP_COPY_BLOCKING) flags |= DMA_COPY_BLOCKING; - copy_bytes = host_get_copy_bytes_normal(dev); + copy_bytes = host_get_copy_bytes_normal(hd, dev); if (!copy_bytes) return 0; @@ -517,10 +443,9 @@ static int host_copy_normal(struct comp_dev *dev) return ret; } -static int create_local_elems(struct comp_dev *dev, uint32_t buffer_count, +static int create_local_elems(struct host_data *hd, struct comp_dev *dev, uint32_t buffer_count, uint32_t buffer_bytes) { - struct host_data *hd = comp_get_drvdata(dev); struct comp_buffer __sparse_cache *dma_buf_c; struct dma_sg_elem_array *elem_array; uint32_t dir; @@ -547,7 +472,7 @@ static int create_local_elems(struct comp_dev *dev, uint32_t buffer_count, dma_buf_c = buffer_acquire(hd->dma_buffer); err = dma_sg_alloc(elem_array, SOF_MEM_ZONE_RUNTIME, dir, buffer_count, buffer_bytes, - (uintptr_t)(dma_buf_c->stream.addr), 0); + (uintptr_t)(audio_stream_get_addr(&dma_buf_c->stream)), 0); buffer_release(dma_buf_c); if (err < 0) { comp_err(dev, "create_local_elems(): dma_sg_alloc() failed"); @@ -567,27 +492,15 @@ static int create_local_elems(struct comp_dev *dev, uint32_t buffer_count, * This function is common for all dma types, with one exception: * dw-dma is run on demand, so no start()/stop() is issued. */ -static int host_trigger(struct comp_dev *dev, int cmd) +int host_zephyr_trigger(struct host_data *hd, struct comp_dev *dev, int cmd) { - struct host_data *hd = comp_get_drvdata(dev); - int ret = 0; - - comp_dbg(dev, "host_trigger()"); - - ret = comp_set_state(dev, cmd); - if (ret < 0) - return ret; - - if (ret == COMP_STATUS_STATE_ALREADY_SET) { - ret = PPL_STATUS_PATH_STOP; - return ret; - } + int ret; /* we should ignore any trigger commands besides start * when doing one shot, because transfers will stop automatically */ if (cmd != COMP_TRIGGER_START && hd->copy_type == COMP_COPY_ONE_SHOT) - return ret; + return 0; if (!hd->chan) { comp_err(dev, "host_trigger(): no dma channel configured"); @@ -609,37 +522,36 @@ static int host_trigger(struct comp_dev *dev, int cmd) ret); break; default: + ret = 0; break; } return ret; } -static struct comp_dev *host_new(const struct comp_driver *drv, - const struct comp_ipc_config *config, - const void *spec) +static int host_trigger(struct comp_dev *dev, int cmd) { - struct comp_dev *dev; - struct host_data *hd; - const struct ipc_config_host *ipc_host = spec; - uint32_t dir; + struct host_data *hd = comp_get_drvdata(dev); + int ret; - comp_cl_dbg(&comp_host, "host_new()"); + comp_dbg(dev, "host_trigger()"); - dev = comp_alloc(drv, sizeof(*dev)); - if (!dev) - return NULL; - dev->ipc_config = *config; + ret = comp_set_state(dev, cmd); + if (ret < 0) + return ret; - hd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*hd)); - if (!hd) { - rfree(dev); - return NULL; - } + if (ret == COMP_STATUS_STATE_ALREADY_SET) + return PPL_STATUS_PATH_STOP; - comp_set_drvdata(dev, hd); - hd->ipc_host = *ipc_host; + return host_zephyr_trigger(hd, dev, cmd); +} +int host_zephyr_new(struct host_data *hd, struct comp_dev *dev, + const struct ipc_config_host *ipc_host, uint32_t config_id) +{ + uint32_t dir; + + hd->ipc_host = *ipc_host; /* request HDA DMA with shared access privilege */ dir = hd->ipc_host.direction == SOF_IPC_STREAM_PLAYBACK ? DMA_DIR_HMEM_TO_LMEM : DMA_DIR_LMEM_TO_HMEM; @@ -647,9 +559,7 @@ static struct comp_dev *host_new(const struct comp_driver *drv, hd->dma = dma_get(dir, 0, DMA_DEV_HOST, DMA_ACCESS_SHARED); if (!hd->dma) { comp_err(dev, "host_new(): dma_get() returned NULL"); - rfree(hd); - rfree(dev); - return NULL; + return -ENODEV; } /* init buffer elems */ @@ -657,43 +567,79 @@ static struct comp_dev *host_new(const struct comp_driver *drv, dma_sg_init(&hd->host.elem_array); dma_sg_init(&hd->local.elem_array); - ipc_build_stream_posn(&hd->posn, SOF_IPC_STREAM_POSITION, dev->ipc_config.id); + ipc_build_stream_posn(&hd->posn, SOF_IPC_STREAM_POSITION, config_id); hd->msg = ipc_msg_init(hd->posn.rhdr.hdr.cmd, hd->posn.rhdr.hdr.size); if (!hd->msg) { comp_err(dev, "host_new(): ipc_msg_init failed"); dma_put(hd->dma); - rfree(hd); - rfree(dev); - return NULL; + return -ENOMEM; } - hd->chan = NULL; hd->copy_type = COMP_COPY_NORMAL; - dev->state = COMP_STATE_READY; - return dev; + return 0; } -static void host_free(struct comp_dev *dev) +static struct comp_dev *host_new(const struct comp_driver *drv, + const struct comp_ipc_config *config, + const void *spec) { - struct host_data *hd = comp_get_drvdata(dev); + struct comp_dev *dev; + struct host_data *hd; + const struct ipc_config_host *ipc_host = spec; + int ret; + + comp_cl_dbg(&comp_host, "host_new()"); - comp_info(dev, "host_free()"); + dev = comp_alloc(drv, sizeof(*dev)); + if (!dev) + return NULL; + dev->ipc_config = *config; + + hd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*hd)); + if (!hd) + goto e_data; + + comp_set_drvdata(dev, hd); + ret = host_zephyr_new(hd, dev, ipc_host, dev->ipc_config.id); + if (ret) + goto e_dev; + + dev->state = COMP_STATE_READY; + + return dev; + +e_dev: + rfree(hd); +e_data: + rfree(dev); + return NULL; +} + +void host_zephyr_free(struct host_data *hd) +{ dma_put(hd->dma); ipc_msg_free(hd->msg); dma_sg_free(&hd->config.elem_array); +} + +static void host_free(struct comp_dev *dev) +{ + struct host_data *hd = comp_get_drvdata(dev); + + comp_dbg(dev, "host_free()"); + host_zephyr_free(hd); rfree(hd); rfree(dev); } -static int host_elements_reset(struct comp_dev *dev) +static int host_elements_reset(struct host_data *hd, struct comp_dev *dev) { - struct host_data *hd = comp_get_drvdata(dev); - struct dma_sg_elem *source_elem = NULL; - struct dma_sg_elem *sink_elem = NULL; + struct dma_sg_elem *source_elem; + struct dma_sg_elem *sink_elem; struct dma_sg_elem *local_elem; /* setup elem to point to first source elem */ @@ -740,10 +686,9 @@ static int host_verify_params(struct comp_dev *dev, } /* configure the DMA params and descriptors for host buffer IO */ -static int host_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) +int host_zephyr_params(struct host_data *hd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, notifier_callback_t cb) { - struct host_data *hd = comp_get_drvdata(dev); struct dma_sg_config *config = &hd->config; struct comp_buffer __sparse_cache *host_buf_c; struct comp_buffer __sparse_cache *dma_buf_c; @@ -754,14 +699,6 @@ static int host_params(struct comp_dev *dev, uint32_t align; int err; - comp_dbg(dev, "host_params()"); - - err = host_verify_params(dev, params); - if (err < 0) { - comp_err(dev, "host_params(): pcm params verification failed."); - return -EINVAL; - } - /* host params always installed by pipeline IPC */ hd->host_size = params->buffer.size; hd->stream_tag = params->stream_tag; @@ -842,7 +779,7 @@ static int host_params(struct comp_dev *dev, */ if (hd->dma_buffer) { dma_buf_c = buffer_acquire(hd->dma_buffer); - err = buffer_set_size(dma_buf_c, buffer_size); + err = buffer_set_size(dma_buf_c, buffer_size, addr_align); buffer_release(dma_buf_c); if (err < 0) { comp_err(dev, "host_params(): buffer_set_size() failed, buffer_size = %u", @@ -850,7 +787,7 @@ static int host_params(struct comp_dev *dev, goto out; } } else { - hd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, + hd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, 0, addr_align); if (!hd->dma_buffer) { comp_err(dev, "host_params(): failed to alloc dma buffer"); @@ -864,7 +801,7 @@ static int host_params(struct comp_dev *dev, } /* create SG DMA elems for local DMA buffer */ - err = create_local_elems(dev, period_count, buffer_size / period_count); + err = create_local_elems(hd, dev, period_count, buffer_size / period_count); if (err < 0) goto out; @@ -876,7 +813,7 @@ static int host_params(struct comp_dev *dev, config->is_scheduling_source = comp_is_scheduling_source(dev); config->period = dev->pipeline->period; - host_elements_reset(dev); + host_elements_reset(hd, dev); hd->stream_tag -= 1; /* get DMA channel from DMAC @@ -909,54 +846,69 @@ static int host_params(struct comp_dev *dev, /* minimal copied data shouldn't be less than alignment */ hd->period_bytes = ALIGN_UP(period_bytes, hd->dma_copy_align); - /* set up callback */ - notifier_register(dev, hd->chan, NOTIFIER_ID_DMA_COPY, host_dma_cb, 0); - /* set copy function */ hd->copy = hd->copy_type == COMP_COPY_ONE_SHOT ? host_copy_one_shot : host_copy_normal; /* set processing function */ - hd->process = pcm_get_conversion_function(host_buf_c->stream.frame_fmt, - host_buf_c->stream.frame_fmt); + hd->process = pcm_get_conversion_function(audio_stream_get_frm_fmt(&host_buf_c->stream), + audio_stream_get_frm_fmt(&host_buf_c->stream)); out: buffer_release(host_buf_c); + + hd->cb_dev = dev; + + if (err >= 0) + /* set up callback */ + notifier_register(dev, hd->chan, NOTIFIER_ID_DMA_COPY, + cb ? : host_dma_cb, 0); + return err; } -static int host_prepare(struct comp_dev *dev) +static int host_params(struct comp_dev *dev, + struct sof_ipc_stream_params *params) { struct host_data *hd = comp_get_drvdata(dev); - struct comp_buffer __sparse_cache *buf_c; - int ret; + int err; - comp_dbg(dev, "host_prepare()"); + comp_dbg(dev, "host_params()"); - ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); - if (ret < 0) - return ret; + err = host_verify_params(dev, params); + if (err < 0) { + comp_err(dev, "host_params(): pcm params verification failed."); + return err; + } - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; + return host_zephyr_params(hd, dev, params, NULL); +} + +int host_zephyr_prepare(struct host_data *hd) +{ + struct comp_buffer __sparse_cache *buf_c = buffer_acquire(hd->dma_buffer); - buf_c = buffer_acquire(hd->dma_buffer); buffer_zero(buf_c); buffer_release(buf_c); return 0; } -static int host_pointer_reset(struct comp_dev *dev) +static int host_prepare(struct comp_dev *dev) { struct host_data *hd = comp_get_drvdata(dev); + int ret; - /* reset buffer pointers */ - hd->local_pos = 0; - hd->report_pos = 0; - hd->total_data_processed = 0; + comp_dbg(dev, "host_prepare()"); - return 0; + ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); + if (ret < 0) + return ret; + + if (ret == COMP_STATUS_STATE_ALREADY_SET) + return PPL_STATUS_PATH_STOP; + + return host_zephyr_prepare(hd); } static int host_position(struct comp_dev *dev, @@ -970,17 +922,14 @@ static int host_position(struct comp_dev *dev, return 0; } -static int host_reset(struct comp_dev *dev) +void host_zephyr_reset(struct host_data *hd, uint16_t state) { - struct host_data *hd = comp_get_drvdata(dev); - - comp_dbg(dev, "host_reset()"); - if (hd->chan) { dma_stop_delayed_legacy(hd->chan); /* remove callback */ - notifier_unregister(dev, hd->chan, NOTIFIER_ID_DMA_COPY); + notifier_unregister(hd->cb_dev, hd->chan, NOTIFIER_ID_DMA_COPY); + dma_channel_put_legacy(hd->chan); hd->chan = NULL; } @@ -999,16 +948,34 @@ static int host_reset(struct comp_dev *dev) hd->dma_buffer = NULL; } - host_pointer_reset(dev); + /* reset buffer pointers */ + hd->local_pos = 0; + hd->report_pos = 0; + hd->total_data_processed = 0; + hd->copy_type = COMP_COPY_NORMAL; hd->source = NULL; hd->sink = NULL; +} + +static int host_reset(struct comp_dev *dev) +{ + struct host_data *hd = comp_get_drvdata(dev); + + comp_dbg(dev, "host_reset()"); + + host_zephyr_reset(hd, dev->state); dev->state = COMP_STATE_READY; return 0; } /* copy and process stream data from source to sink buffers */ +int host_zephyr_copy(struct host_data *hd, struct comp_dev *dev, copy_callback_t cb) +{ + return hd->copy(hd, dev, cb); +} + static int host_copy(struct comp_dev *dev) { struct host_data *hd = comp_get_drvdata(dev); @@ -1016,7 +983,7 @@ static int host_copy(struct comp_dev *dev) if (dev->state != COMP_STATE_ACTIVE) return 0; - return hd->copy(dev); + return host_zephyr_copy(hd, dev, NULL); } static int host_get_attribute(struct comp_dev *dev, uint32_t type, diff --git a/src/audio/host-zephyr.c b/src/audio/host-zephyr.c index 94e6f8daa6c0..80c0c5ac5cf0 100644 --- a/src/audio/host-zephyr.c +++ b/src/audio/host-zephyr.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -74,7 +73,8 @@ static uint32_t host_dma_get_split(struct host_data *hd, uint32_t bytes) #if CONFIG_FORCE_DMA_COPY_WHOLE_BLOCK -static int host_dma_set_config_and_copy(struct host_data *hd, struct comp_dev *dev, uint32_t bytes) +static int host_dma_set_config_and_copy(struct host_data *hd, struct comp_dev *dev, uint32_t bytes, + copy_callback_t cb) { struct dma_sg_elem *local_elem = hd->config.elem_array.elems; int ret; @@ -89,12 +89,8 @@ static int host_dma_set_config_and_copy(struct host_data *hd, struct comp_dev *d return ret; } - struct dma_cb_data next = { - .channel = hd->chan, - .elem = { .size = bytes }, - }; - notifier_event(hd->chan, NOTIFIER_ID_DMA_COPY, - NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + cb(dev, bytes); + ret = dma_reload(hd->chan->dma->z_dev, hd->chan->index, 0, 0, bytes); if (ret < 0) { comp_err(dev, "host_dma_set_config_and_copy(): dma_copy() failed, ret = %d", @@ -138,7 +134,7 @@ static uint32_t host_get_copy_bytes_one_shot(struct host_data *hd) * @param dev Host component device. * @return 0 if succeeded, error code otherwise. */ -static int host_copy_one_shot(struct host_data *hd, struct comp_dev *dev) +static int host_copy_one_shot(struct host_data *hd, struct comp_dev *dev, copy_callback_t cb) { uint32_t copy_bytes; uint32_t split_value; @@ -157,7 +153,7 @@ static int host_copy_one_shot(struct host_data *hd, struct comp_dev *dev) split_value = host_dma_get_split(hd, copy_bytes); copy_bytes -= split_value; - ret = host_dma_set_config_and_copy(hd, dev, copy_bytes); + ret = host_dma_set_config_and_copy(hd, dev, copy_bytes, cb); if (ret < 0) return ret; @@ -213,7 +209,7 @@ static uint32_t host_get_copy_bytes_one_shot(struct host_data *hd) * @param dev Host component device. * @return 0 if succeeded, error code otherwise. */ -static int host_copy_one_shot(struct host_data *hd, struct comp_dev *dev) +static int host_copy_one_shot(struct host_data *hd, struct comp_dev *dev, copy_callback_t cb) { uint32_t copy_bytes; int ret = 0; @@ -233,12 +229,8 @@ static int host_copy_one_shot(struct host_data *hd, struct comp_dev *dev) return ret; } - struct dma_cb_data next = { - .channel = hd->chan, - .elem = { .size = copy_bytes }, - }; - notifier_event(hd->chan, NOTIFIER_ID_DMA_COPY, - NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + cb(dev, copy_bytes); + ret = dma_reload(hd->chan->dma->z_dev, hd->chan->index, 0, 0, copy_bytes); if (ret < 0) comp_err(dev, "host_copy_one_shot(): dma_copy() failed, ret = %u", ret); @@ -365,12 +357,9 @@ void host_one_shot_cb(struct host_data *hd, uint32_t bytes) /* This is called by DMA driver every time when DMA completes its current * transfer between host and DSP. */ -void host_dma_cb(void *arg, enum notify_id type, void *data) +static void host_dma_cb(struct comp_dev *dev, size_t bytes) { - struct dma_cb_data *next = data; - struct comp_dev *dev = arg; struct host_data *hd = comp_get_drvdata(dev); - uint32_t bytes = next->elem.size; comp_cl_dbg(&comp_host, "host_dma_cb() %p", &comp_host); @@ -391,50 +380,57 @@ static uint32_t host_get_copy_bytes_normal(struct host_data *hd, struct comp_dev { struct comp_buffer *buffer = hd->local_buffer; struct comp_buffer __sparse_cache *buffer_c; - struct dma_status stat; - uint32_t avail_bytes; - uint32_t free_bytes; - uint32_t copy_bytes; + struct comp_buffer __sparse_cache *dma_buf_c; + struct dma_status dma_stat; + uint32_t avail_samples; + uint32_t free_samples; + uint32_t dma_sample_bytes; + uint32_t dma_copy_bytes; int ret; /* get data sizes from DMA */ - ret = dma_get_status(hd->chan->dma->z_dev, hd->chan->index, &stat); + ret = dma_get_status(hd->chan->dma->z_dev, hd->chan->index, &dma_stat); if (ret < 0) { comp_err(dev, "host_get_copy_bytes_normal(): dma_get_status() failed, ret = %u", ret); /* return 0 copy_bytes in case of error to skip DMA copy */ return 0; } - avail_bytes = stat.pending_length; - free_bytes = stat.free; + + dma_buf_c = buffer_acquire(hd->dma_buffer); + dma_sample_bytes = get_sample_bytes(dma_buf_c->stream.frame_fmt); + buffer_release(dma_buf_c); buffer_c = buffer_acquire(buffer); /* calculate minimum size to copy */ - if (dev->direction == SOF_IPC_STREAM_PLAYBACK) - free_bytes = audio_stream_get_free_bytes(&buffer_c->stream); - else - avail_bytes = audio_stream_get_avail_bytes(&buffer_c->stream); + if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { + avail_samples = dma_stat.pending_length / dma_sample_bytes; + free_samples = audio_stream_get_free_samples(&buffer_c->stream); + } else { + avail_samples = audio_stream_get_avail_samples(&buffer_c->stream); + free_samples = dma_stat.free / dma_sample_bytes; + } - copy_bytes = MIN(avail_bytes, free_bytes); + dma_copy_bytes = MIN(avail_samples, free_samples) * dma_sample_bytes; /* limit bytes per copy to one period for the whole pipeline * in order to avoid high load spike * if FAST_MODE is enabled, then one period limitation is omitted */ if (!(hd->ipc_host.feature_mask & BIT(IPC4_COPIER_FAST_MODE))) - copy_bytes = MIN(hd->period_bytes, copy_bytes); + dma_copy_bytes = MIN(hd->period_bytes, dma_copy_bytes); - if (!copy_bytes) - comp_info(dev, "no bytes to copy, available bytes: %d, free_bytes: %d", - avail_bytes, free_bytes); + if (!dma_copy_bytes) + comp_info(dev, "no bytes to copy, available samples: %d, free_samples: %d", + avail_samples, free_samples); buffer_release(buffer_c); - /* copy_bytes should be aligned to minimum possible chunk of + /* dma_copy_bytes should be aligned to minimum possible chunk of * data to be copied by dma. */ - return ALIGN_DOWN(copy_bytes, hd->dma_copy_align); + return ALIGN_DOWN(dma_copy_bytes, hd->dma_copy_align); } /** @@ -443,7 +439,7 @@ static uint32_t host_get_copy_bytes_normal(struct host_data *hd, struct comp_dev * @param dev Host component device. * @return 0 if succeeded, error code otherwise. */ -static int host_copy_normal(struct host_data *hd, struct comp_dev *dev) +static int host_copy_normal(struct host_data *hd, struct comp_dev *dev, copy_callback_t cb) { struct comp_buffer __sparse_cache *buffer_c; uint32_t copy_bytes; @@ -460,12 +456,7 @@ static int host_copy_normal(struct host_data *hd, struct comp_dev *dev) if (!copy_bytes) return 0; - struct dma_cb_data next = { - .channel = hd->chan, - .elem = { .size = copy_bytes }, - }; - notifier_event(hd->chan, NOTIFIER_ID_DMA_COPY, - NOTIFIER_TARGET_CORE_LOCAL, &next, sizeof(next)); + cb(dev, copy_bytes); hd->partial_size += copy_bytes; buffer_c = buffer_acquire(hd->dma_buffer); @@ -477,8 +468,9 @@ static int host_copy_normal(struct host_data *hd, struct comp_dev *dev) * also adding a 2ms safety margin. */ if (!IS_ENABLED(CONFIG_HOST_DMA_RELOAD_DELAY_ENABLE) || - buffer_c->stream.size < hd->period_bytes << 3 || - buffer_c->stream.size - hd->partial_size <= (2 + threshold) * hd->period_bytes) { + audio_stream_get_size(&buffer_c->stream) < hd->period_bytes << 3 || + audio_stream_get_size(&buffer_c->stream) - hd->partial_size <= + (2 + threshold) * hd->period_bytes) { ret = dma_reload(hd->chan->dma->z_dev, hd->chan->index, 0, 0, hd->partial_size); if (ret < 0) comp_err(dev, "host_copy_normal(): dma_copy() failed, ret = %u", ret); @@ -520,7 +512,7 @@ static int create_local_elems(struct host_data *hd, struct comp_dev *dev, uint32 dma_buf_c = buffer_acquire(hd->dma_buffer); err = dma_sg_alloc(elem_array, SOF_MEM_ZONE_RUNTIME, dir, buffer_count, buffer_bytes, - (uintptr_t)(dma_buf_c->stream.addr), 0); + (uintptr_t)audio_stream_get_addr(&dma_buf_c->stream), 0); buffer_release(dma_buf_c); if (err < 0) { comp_err(dev, "create_local_elems(): dma_sg_alloc() failed"); @@ -530,6 +522,16 @@ static int create_local_elems(struct host_data *hd, struct comp_dev *dev, uint32 return 0; } +/** + * \brief Command handler. + * \param[in,out] dev Device + * \param[in] cmd Command + * \return 0 if successful, error code otherwise. + * + * Used to pass standard and bespoke commands (with data) to component. + * This function is common for all dma types, with one exception: + * dw-dma is run on demand, so no start()/stop() is issued. + */ int host_zephyr_trigger(struct host_data *hd, struct comp_dev *dev, int cmd) { int ret = 0; @@ -555,13 +557,10 @@ int host_zephyr_trigger(struct host_data *hd, struct comp_dev *dev, int cmd) break; case COMP_TRIGGER_STOP: case COMP_TRIGGER_XRUN: - if (dev->state == COMP_STATE_ACTIVE) { - ret = dma_stop(hd->chan->dma->z_dev, hd->chan->index); - if (ret < 0) - comp_err(dev, "host_trigger(): dma stop failed: %d", - ret); - } - + ret = dma_stop(hd->chan->dma->z_dev, hd->chan->index); + if (ret < 0) + comp_err(dev, "host_trigger(): dma stop failed: %d", + ret); break; default: break; @@ -570,16 +569,6 @@ int host_zephyr_trigger(struct host_data *hd, struct comp_dev *dev, int cmd) return ret; } -/** - * \brief Command handler. - * \param[in,out] dev Device - * \param[in] cmd Command - * \return 0 if successful, error code otherwise. - * - * Used to pass standard and bespoke commands (with data) to component. - * This function is common for all dma types, with one exception: - * dw-dma is run on demand, so no start()/stop() is issued. - */ static int host_trigger(struct comp_dev *dev, int cmd) { struct host_data *hd = comp_get_drvdata(dev); @@ -736,8 +725,9 @@ static int host_verify_params(struct comp_dev *dev, return 0; } +/* configure the DMA params and descriptors for host buffer IO */ int host_zephyr_params(struct host_data *hd, struct comp_dev *dev, - struct sof_ipc_stream_params *params) + struct sof_ipc_stream_params *params, notifier_callback_t cb) { struct dma_sg_config *config = &hd->config; struct dma_sg_elem *sg_elem; @@ -830,7 +820,7 @@ int host_zephyr_params(struct host_data *hd, struct comp_dev *dev, */ if (hd->dma_buffer) { dma_buf_c = buffer_acquire(hd->dma_buffer); - err = buffer_set_size(dma_buf_c, buffer_size); + err = buffer_set_size(dma_buf_c, buffer_size, addr_align); buffer_release(dma_buf_c); if (err < 0) { comp_err(dev, "host_params(): buffer_set_size() failed, buffer_size = %u", @@ -838,7 +828,7 @@ int host_zephyr_params(struct host_data *hd, struct comp_dev *dev, goto out; } } else { - hd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, + hd->dma_buffer = buffer_alloc(buffer_size, SOF_MEM_CAPS_DMA, 0, addr_align); if (!hd->dma_buffer) { comp_err(dev, "host_params(): failed to alloc dma buffer"); @@ -851,11 +841,13 @@ int host_zephyr_params(struct host_data *hd, struct comp_dev *dev, /* set processing function */ if (params->direction == SOF_IPC_STREAM_CAPTURE) - hd->process = pcm_get_conversion_function(host_buf_c->stream.frame_fmt, - dma_buf_c->stream.frame_fmt); + hd->process = pcm_get_conversion_function( + audio_stream_get_frm_fmt(&host_buf_c->stream), + audio_stream_get_frm_fmt(&dma_buf_c->stream)); else - hd->process = pcm_get_conversion_function(dma_buf_c->stream.frame_fmt, - host_buf_c->stream.frame_fmt); + hd->process = pcm_get_conversion_function( + audio_stream_get_frm_fmt(&dma_buf_c->stream), + audio_stream_get_frm_fmt(&host_buf_c->stream)); config->src_width = audio_stream_sample_bytes(&dma_buf_c->stream); config->dest_width = config->src_width; @@ -962,7 +954,6 @@ int host_zephyr_params(struct host_data *hd, struct comp_dev *dev, return err; } -/* configure the DMA params and descriptors for host buffer IO */ static int host_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { @@ -977,12 +968,7 @@ static int host_params(struct comp_dev *dev, return err; } - err = host_zephyr_params(hd, dev, params); - if (err >= 0) - /* set up callback */ - notifier_register(dev, hd->chan, NOTIFIER_ID_DMA_COPY, host_dma_cb, 0); - - return err; + return host_zephyr_params(hd, dev, params, NULL); } int host_zephyr_prepare(struct host_data *hd) @@ -1009,7 +995,6 @@ static int host_prepare(struct comp_dev *dev) if (ret == COMP_STATUS_STATE_ALREADY_SET) return PPL_STATUS_PATH_STOP; - return host_zephyr_prepare(hd); } @@ -1027,8 +1012,7 @@ static int host_position(struct comp_dev *dev, void host_zephyr_reset(struct host_data *hd, uint16_t state) { if (hd->chan) { - if (state == COMP_STATE_ACTIVE) - dma_stop(hd->chan->dma->z_dev, hd->chan->index); + dma_stop(hd->chan->dma->z_dev, hd->chan->index); dma_release_channel(hd->dma->z_dev, hd->chan->index); hd->chan = NULL; } @@ -1059,9 +1043,6 @@ static int host_reset(struct comp_dev *dev) struct host_data *hd = comp_get_drvdata(dev); comp_dbg(dev, "host_reset()"); - /* remove callback first for host reset */ - if (hd->chan) - notifier_unregister(dev, hd->chan, NOTIFIER_ID_DMA_COPY); host_zephyr_reset(hd, dev->state); dev->state = COMP_STATE_READY; @@ -1070,12 +1051,11 @@ static int host_reset(struct comp_dev *dev) } /* copy and process stream data from source to sink buffers */ -int host_zephyr_copy(struct host_data *hd, struct comp_dev *dev) +int host_zephyr_copy(struct host_data *hd, struct comp_dev *dev, copy_callback_t cb) { - return hd->copy(hd, dev); + return hd->copy(hd, dev, cb); } -/* copy and process stream data from source to sink buffers */ static int host_copy(struct comp_dev *dev) { struct host_data *hd = comp_get_drvdata(dev); @@ -1083,7 +1063,7 @@ static int host_copy(struct comp_dev *dev) if (dev->state != COMP_STATE_ACTIVE) return 0; - return host_zephyr_copy(hd, dev); + return host_zephyr_copy(hd, dev, host_dma_cb); } static int host_get_attribute(struct comp_dev *dev, uint32_t type, diff --git a/src/audio/igo_nr/igo_nr.c b/src/audio/igo_nr/igo_nr.c index 4fcc3f11f815..56803a8985f4 100755 --- a/src/audio/igo_nr/igo_nr.c +++ b/src/audio/igo_nr/igo_nr.c @@ -70,7 +70,7 @@ static void igo_nr_capture_s16(struct comp_data *cd, struct audio_stream __sparse_cache *sink, int32_t frames) { - int32_t nch = source->channels; + int32_t nch = audio_stream_get_channels(source); int32_t i; int32_t j; int32_t idx_in = 0; @@ -129,7 +129,7 @@ static void igo_nr_capture_s24(struct comp_data *cd, struct audio_stream __sparse_cache *sink, int32_t frames) { - int32_t nch = source->channels; + int32_t nch = audio_stream_get_channels(source); int32_t i; int32_t j; int32_t idx_in = 0; @@ -188,7 +188,7 @@ static void igo_nr_capture_s32(struct comp_data *cd, struct audio_stream __sparse_cache *sink, int32_t frames) { - int32_t nch = source->channels; + int32_t nch = audio_stream_get_channels(source); int32_t i; int32_t j; int32_t idx_in = 0; @@ -249,7 +249,7 @@ static inline int32_t set_capture_func(struct comp_dev *dev) sink_list); /* The igo_nr supports S16_LE data. Format converter is needed. */ - switch (sourceb->stream.frame_fmt) { + switch (audio_stream_get_frm_fmt(&sourceb->stream)) { #if CONFIG_FORMAT_S16LE case SOF_IPC_FRAME_S16_LE: comp_info(dev, "set_capture_func(), SOF_IPC_FRAME_S16_LE"); @@ -399,10 +399,10 @@ static int32_t igo_nr_params(struct comp_dev *dev, sink_c = buffer_acquire(sinkb); /* set source/sink_frames/rate */ - cd->source_rate = source_c->stream.rate; - cd->sink_rate = sink_c->stream.rate; + cd->source_rate = audio_stream_get_rate(&source_c->stream); + cd->sink_rate = audio_stream_get_rate(&sink_c->stream); - if (source_c->stream.channels != sink_c->stream.channels) { + if (source_c->stream.channels != audio_stream_get_channels(&sink_c->stream)) { comp_err(dev, "igo_nr_params(), mismatch source/sink stream channels"); cd->invalid_param = true; } diff --git a/src/audio/kpb.c b/src/audio/kpb.c index aa064a648f4f..b3af7cfbe70b 100644 --- a/src/audio/kpb.c +++ b/src/audio/kpb.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -47,6 +46,13 @@ #include #include #include +#if CONFIG_AMS +#include +#include +#include +#else +#include +#endif static const struct comp_driver comp_kpb; @@ -100,11 +106,17 @@ struct comp_data { uint32_t num_of_in_channels; uint32_t offsets[KPB_MAX_MICSEL_CHANNELS]; struct kpb_micselector_config mic_sel; + +#if CONFIG_AMS + uint32_t kpd_uuid_id; +#endif }; /*! KPB private functions */ +#ifndef CONFIG_AMS static void kpb_event_handler(void *arg, enum notify_id type, void *event_data); static int kpb_register_client(struct comp_data *kpb, struct kpb_client *cli); +#endif static void kpb_init_draining(struct comp_dev *dev, struct kpb_client *cli); static enum task_state kpb_draining_task(void *arg); static int kpb_buffer_data(struct comp_dev *dev, @@ -135,6 +147,25 @@ static uint64_t kpb_task_deadline(void *data) return SOF_TASK_DEADLINE_ALMOST_IDLE; } +#if CONFIG_AMS + +/* Key-phrase detected message*/ +static const ams_uuid_t ams_kpd_msg_uuid = AMS_KPD_MSG_UUID; + +/* Key-phrase detected notification handler*/ +static void kpb_ams_kpd_notification(const struct ams_message_payload *const ams_message_payload, + void *ctx) +{ + struct kpb_client *cli_data = (struct kpb_client *)ams_message_payload->message; + struct comp_dev *dev = ctx; + + comp_dbg(dev, "kpb_ams_kpd_notification()"); + + kpb_init_draining(dev, cli_data); +} + +#endif /* CONFIG_AMS */ + #ifdef __ZEPHYR__ static void kpb_lock(struct comp_data *kpb) @@ -222,7 +253,7 @@ static void kpb_set_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { struct comp_data *kpb = comp_get_drvdata(dev); - uint32_t __sparse_cache valid_fmt, frame_fmt; + enum sof_ipc_frame frame_fmt, valid_fmt; comp_dbg(dev, "kpb_set_params()"); @@ -620,8 +651,18 @@ static void kpb_free(struct comp_dev *dev) comp_info(dev, "kpb_free()"); +#if CONFIG_AMS + /* Unregister KPB as AMS consumer */ + int ret; + + ret = ams_helper_unregister_consumer(dev, kpb->kpd_uuid_id, + kpb_ams_kpd_notification); + if (ret) + comp_err(dev, "kpb_free(): AMS unregister error %d", ret); +#else /* Unregister KPB from notifications */ notifier_unregister(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT); +#endif/* CONFIG_AMS */ /* Reclaim memory occupied by history buffer */ kpb_free_history_buffer(kpb->hd.c_hb); @@ -697,6 +738,10 @@ static int kpb_params(struct comp_dev *dev, kpb->host_period_size = params->host_period_bytes; kpb->config.sampling_width = params->sample_container_bytes * 8; +#if CONFIG_AMS + kpb->kpd_uuid_id = AMS_INVALID_MSG_TYPE; +#endif + return 0; } @@ -772,9 +817,17 @@ static int kpb_prepare(struct comp_dev *dev) kpb->clients[i].r_ptr = NULL; } +#if CONFIG_AMS + /* AMS Register KPB for notification */ + ret = ams_helper_register_consumer(dev, &kpb->kpd_uuid_id, + ams_kpd_msg_uuid, + kpb_ams_kpd_notification); +#else /* Register KPB for notification */ ret = notifier_register(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT, kpb_event_handler, 0); +#endif /* CONFIG_AMS */ + if (ret < 0) { kpb_free_history_buffer(kpb->hd.c_hb); kpb->hd.c_hb = NULL; @@ -835,9 +888,9 @@ static int kpb_prepare(struct comp_dev *dev) sink_id = sink_c->id; if (sink_id == 0) - sink_c->stream.channels = kpb->num_of_sel_mic; + audio_stream_set_channels(&sink_c->stream, kpb->num_of_sel_mic); else - sink_c->stream.channels = kpb->config.channels; + audio_stream_set_channels(&sink_c->stream, kpb->config.channels); buffer_release(sink_c); } @@ -917,8 +970,10 @@ static int kpb_reset(struct comp_dev *dev) kpb_reset_history_buffer(kpb->hd.c_hb); } +#ifndef CONFIG_AMS /* Unregister KPB from notifications */ notifier_unregister(dev, NULL, NOTIFIER_ID_KPB_CLIENT_EVT); +#endif /* Finally KPB is ready after reset */ kpb_change_state(kpb, KPB_STATE_PREPARING); @@ -940,11 +995,11 @@ static void kpb_micselect_copy16(struct comp_buffer __sparse_cache *sink, uint16_t ch; size_t i; - AE_SETCBEGIN0(ostream->addr); - AE_SETCEND0(ostream->end_addr); + AE_SETCBEGIN0(audio_stream_get_addr(ostream)); + AE_SETCEND0(audio_stream_get_end_addr(ostream)); buffer_stream_invalidate(source, size); - const ae_int16 *in_ptr = (const ae_int16 *)istream->r_ptr; + const ae_int16 *in_ptr = audio_stream_get_rptr(istream); ae_int16x4 d16 = AE_ZERO16(); const size_t in_offset = in_channels * sizeof(ae_int16); const size_t out_offset = micsel_channels * sizeof(ae_int16); @@ -954,7 +1009,7 @@ static void kpb_micselect_copy16(struct comp_buffer __sparse_cache *sink, for (ch = 0; ch < micsel_channels; ch++) { const ae_int16 *input_data = (const ae_int16 *)(in_ptr) + offsets[ch]; - out_ptr = (ae_int16 *)ostream->w_ptr; + out_ptr = audio_stream_get_wptr(ostream); out_ptr += ch; for (i = 0; i < samples_per_chan; i++) { AE_L16_XP(d16, input_data, in_offset); @@ -973,12 +1028,12 @@ static void kpb_micselect_copy32(struct comp_buffer __sparse_cache *sink, uint16_t ch; size_t i; - AE_SETCBEGIN0(ostream->addr); - AE_SETCEND0(ostream->end_addr); + AE_SETCBEGIN0(audio_stream_get_addr(ostream)); + AE_SETCEND0(audio_stream_get_end_addr(ostream)); buffer_stream_invalidate(source, size); - const ae_int32 *in_ptr = (const ae_int32 *)istream->r_ptr; + const ae_int32 *in_ptr = audio_stream_get_rptr(istream); ae_int32x2 d32 = AE_ZERO32(); const size_t in_offset = in_channels * sizeof(ae_int32); const size_t out_offset = micsel_channels * sizeof(ae_int32); @@ -988,7 +1043,7 @@ static void kpb_micselect_copy32(struct comp_buffer __sparse_cache *sink, for (ch = 0; ch < micsel_channels; ch++) { const ae_int32 *input_data = (const ae_int32 *)(in_ptr) + offsets[ch]; - out_ptr = (ae_int32 *)ostream->w_ptr; + out_ptr = audio_stream_get_wptr(ostream); out_ptr += ch; for (i = 0; i < samples_per_chan; i++) { AE_L32_XP(d32, input_data, in_offset); @@ -1015,13 +1070,13 @@ static void kpb_micselect_copy16(struct comp_buffer __sparse_cache *sink, for (ch = 0; ch < micsel_channels; ch++) { out_samples = 0; - in_data = (int16_t *)istream->r_ptr; - out_data = (int16_t *)ostream->w_ptr; + in_data = audio_stream_get_rptr(istream); + out_data = audio_stream_get_wptr(ostream); for (size_t i = 0; i < samples_per_chan * in_channels; i += in_channels) { if (&out_data[out_samples + ch] - >= (int16_t *)ostream->end_addr) { - out_data = (int16_t *)ostream->addr; + >= (int16_t *)audio_stream_get_end_addr(ostream)) { + out_data = (int16_t *)audio_stream_get_addr(ostream); out_samples = 0; } out_data[out_samples + ch] = in_data[i + offsets[ch]]; @@ -1046,13 +1101,13 @@ static void kpb_micselect_copy32(struct comp_buffer __sparse_cache *sink, for (ch = 0; ch < micsel_channels; ch++) { out_samples = 0; - in_data = (int32_t *)istream->r_ptr; - out_data = (int32_t *)ostream->w_ptr; + in_data = audio_stream_get_rptr(istream); + out_data = audio_stream_get_wptr(ostream); for (size_t i = 0; i < samples_per_chan * in_channels; i += in_channels) { if (&out_data[out_samples + ch] - >= (int32_t *)ostream->end_addr) { - out_data = (int32_t *)ostream->addr; + >= (int32_t *)audio_stream_get_end_addr(ostream)) { + out_data = (int32_t *)audio_stream_get_addr(ostream); out_samples = 0; } out_data[out_samples + ch] = in_data[i + offsets[ch]]; @@ -1128,7 +1183,7 @@ static int kpb_copy(struct comp_dev *dev) source_c = buffer_acquire(source); /* Validate source */ - if (!source_c->stream.r_ptr) { + if (!audio_stream_get_rptr(&source_c->stream)) { comp_err(dev, "kpb_copy(): invalid source pointers."); ret = -EINVAL; goto out; @@ -1149,7 +1204,7 @@ static int kpb_copy(struct comp_dev *dev) sink_c = buffer_acquire(sink); /* Validate sink */ - if (!sink_c->stream.w_ptr) { + if (!audio_stream_get_wptr(&sink_c->stream)) { comp_err(dev, "kpb_copy(): invalid selector sink pointers."); ret = -EINVAL; break; @@ -1229,7 +1284,7 @@ static int kpb_copy(struct comp_dev *dev) sink_c = buffer_acquire(sink); /* Validate sink */ - if (!sink_c->stream.w_ptr) { + if (!audio_stream_get_wptr(&sink_c->stream)) { comp_err(dev, "kpb_copy(): invalid host sink pointers."); ret = -EINVAL; break; @@ -1422,6 +1477,7 @@ static int kpb_buffer_data(struct comp_dev *dev, return ret; } +#ifndef CONFIG_AMS /** * \brief Main event dispatcher. * \param[in] arg - KPB component internal data. @@ -1501,6 +1557,7 @@ static int kpb_register_client(struct comp_data *kpb, struct kpb_client *cli) return ret; } +#endif /* CONFIG_AMS */ /** * \brief Prepare history buffer for draining. @@ -1823,12 +1880,13 @@ static void kpb_convert_24b_to_32b(const void *linear_source, int ioffset, { int ssize = audio_stream_sample_bytes(sink); uint8_t *in = (uint8_t *)linear_source + ioffset * ssize; - uint8_t *out = audio_stream_wrap(sink, (uint8_t *)sink->w_ptr + ooffset * ssize); + uint8_t *out = audio_stream_wrap(sink, (uint8_t *)audio_stream_get_wptr(sink) + + ooffset * ssize); ae_int32x2 *buf_end; ae_int32x2 *buf; - buf = (ae_int32x2 *)(sink->addr); - buf_end = (ae_int32x2 *)(sink->end_addr); + buf = (ae_int32x2 *)(audio_stream_get_addr(sink)); + buf_end = audio_stream_get_end_addr(sink); ae_int32x2 *out_ptr = (ae_int32x2 *)buf; AE_SETCBEGIN0(buf); @@ -1870,7 +1928,8 @@ static void kpb_convert_24b_to_32b(const void *source, int ioffset, { int ssize = audio_stream_sample_bytes(sink); uint8_t *src = (uint8_t *)source + ioffset * 3; - int32_t *dst = audio_stream_wrap(sink, (uint8_t *)sink->w_ptr + ooffset * ssize); + int32_t *dst = audio_stream_wrap(sink, (uint8_t *)audio_stream_get_wptr(sink) + + ooffset * ssize); int processed; int nmax, i, n; @@ -1910,7 +1969,7 @@ static void kpb_drain_samples(void *source, struct audio_stream __sparse_cache * #endif /* CONFIG_FORMAT_S16LE */ #if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE case 24: - samples = size / ((sample_width >> 3) * sink->channels); + samples = size / ((sample_width >> 3) * audio_stream_get_channels(sink)); kpb_convert_24b_to_32b(source, 0, sink, 0, samples); break; case 32: @@ -1929,7 +1988,8 @@ static void kpb_convert_32b_to_24b(const struct audio_stream __sparse_cache *sou void *linear_sink, int ooffset, unsigned int n_samples) { int ssize = audio_stream_sample_bytes(source); - uint8_t *in = audio_stream_wrap(source, (uint8_t *)source->r_ptr + ioffset * ssize); + uint8_t *in = audio_stream_wrap(source, (uint8_t *)audio_stream_get_rptr(source) + + ioffset * ssize); uint8_t *out = (uint8_t *)linear_sink + ooffset * ssize; const ae_f24x2 *sin = (const ae_f24x2 *)in; @@ -1966,7 +2026,8 @@ static void kpb_convert_32b_to_24b(const struct audio_stream __sparse_cache *sou void *sink, int ooffset, unsigned int samples) { int ssize = audio_stream_sample_bytes(source); - int32_t *src = audio_stream_wrap(source, (uint8_t *)source->r_ptr + ioffset * ssize); + int32_t *src = audio_stream_wrap(source, (uint8_t *)audio_stream_get_rptr(source) + + ioffset * ssize); uint8_t *dst = (uint8_t *)sink + ooffset * 3; int processed; int nmax, i, n; @@ -2012,8 +2073,8 @@ static void kpb_buffer_samples(const struct audio_stream __sparse_cache *source, #endif #if CONFIG_FORMAT_S24LE || CONFIG_FORMAT_S32LE case 24: - samples_count = size / ((sample_width >> 3) * source->channels); - samples_offset = offset / ((sample_width >> 3) * source->channels); + samples_count = size / ((sample_width >> 3) * audio_stream_get_channels(source)); + samples_offset = offset / ((sample_width >> 3) * audio_stream_get_channels(source)); kpb_convert_32b_to_24b(source, samples_offset, sink, 0, samples_count); break; @@ -2086,8 +2147,10 @@ static void kpb_copy_24b_in_32b(const struct audio_stream __sparse_cache *source uint32_t n_samples) { int ssize = audio_stream_sample_bytes(source); /* src fmt == sink fmt */ - uint8_t *in = audio_stream_wrap(source, (uint8_t *)source->r_ptr + ioffset * ssize); - uint8_t *out = audio_stream_wrap(sink, (uint8_t *)sink->w_ptr + ooffset * ssize); + uint8_t *in = audio_stream_wrap(source, (uint8_t *)audio_stream_get_rptr(source) + + ioffset * ssize); + uint8_t *out = audio_stream_wrap(sink, (uint8_t *)audio_stream_get_wptr(sink) + + ooffset * ssize); const ae_int32x2 *sin = (const ae_int32x2 *)in; ae_int32x2 *sout = (ae_int32x2 *)out; @@ -2117,8 +2180,8 @@ static void kpb_copy_24b_in_32b(const struct audio_stream __sparse_cache *source uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; diff --git a/src/audio/mfcc/mfcc.c b/src/audio/mfcc/mfcc.c index ac5065b3a1a7..a269615abb1e 100644 --- a/src/audio/mfcc/mfcc.c +++ b/src/audio/mfcc/mfcc.c @@ -209,19 +209,19 @@ static int mfcc_prepare(struct processing_module *mod) sink_c = buffer_acquire(sinkb); /* get source data format */ - source_format = source_c->stream.frame_fmt; + source_format = audio_stream_get_frm_fmt(&source_c->stream); /* set align requirements */ mfcc_set_alignment(&source_c->stream, &sink_c->stream); /* get sink data format and period bytes */ - sink_format = sink_c->stream.frame_fmt; + sink_format = audio_stream_get_frm_fmt(&sink_c->stream); sink_period_bytes = audio_stream_period_bytes(&sink_c->stream, dev->frames); comp_info(dev, "mfcc_prepare(), source_format = %d, sink_format = %d", source_format, sink_format); - if (sink_c->stream.size < sink_period_bytes) { + if (audio_stream_get_size(&sink_c->stream) < sink_period_bytes) { comp_err(dev, "mfcc_prepare(): sink buffer size %d is insufficient < %d", - sink_c->stream.size, sink_period_bytes); + audio_stream_get_size(&sink_c->stream), sink_period_bytes); ret = -ENOMEM; goto err; } @@ -230,8 +230,8 @@ static int mfcc_prepare(struct processing_module *mod) /* Initialize MFCC, max_frames is set to dev->frames + 4 */ if (cd->config) { - ret = mfcc_setup(mod, dev->frames + 4, source_c->stream.rate, - source_c->stream.channels); + ret = mfcc_setup(mod, dev->frames + 4, audio_stream_get_rate(&source_c->stream), + audio_stream_get_channels(&source_c->stream)); if (ret < 0) { comp_err(dev, "mfcc_prepare(), setup failed."); goto err; diff --git a/src/audio/mfcc/mfcc_generic.c b/src/audio/mfcc/mfcc_generic.c index baea55b15f5c..6294b02dd059 100644 --- a/src/audio/mfcc/mfcc_generic.c +++ b/src/audio/mfcc/mfcc_generic.c @@ -93,7 +93,7 @@ static void mfcc_source_copy_s16(struct input_stream_buffer *bsource, struct mfc struct audio_stream __sparse_cache *source = bsource->data; int32_t s; int16_t *x0; - int16_t *x = source->r_ptr; + int16_t *x = audio_stream_get_rptr(source); int16_t *w = buf->w_ptr; int copied; int nmax; @@ -101,7 +101,7 @@ static void mfcc_source_copy_s16(struct input_stream_buffer *bsource, struct mfc int n2; int n; int i; - int num_channels = source->channels; + int num_channels = audio_stream_get_channels(source); /* Copy from source to pre-buffer for FFT. * The pre-emphasis filter is done in this step. @@ -126,7 +126,7 @@ static void mfcc_source_copy_s16(struct input_stream_buffer *bsource, struct mfc w++; } - x = audio_stream_wrap(source, x + n * source->channels); + x = audio_stream_wrap(source, x + n * audio_stream_get_channels(source)); w = mfcc_buffer_wrap(buf, w); } buf->s_avail += copied; @@ -462,7 +462,7 @@ void mfcc_s16_default(struct processing_module *mod, struct input_stream_buffer struct mfcc_state *state = &cd->state; struct mfcc_buffer *buf = &cd->state.buf; uint32_t magic = MFCC_MAGIC; - int16_t *w_ptr = sink->w_ptr; + int16_t *w_ptr = audio_stream_get_wptr(sink); int num_magic = sizeof(magic) / sizeof(int16_t); int num_ceps; int zero_samples; @@ -478,7 +478,7 @@ void mfcc_s16_default(struct processing_module *mod, struct input_stream_buffer /* Done, copy data to sink. This works only if the period has room for magic (2) * plus num_ceps int16_t samples. TODO: split ceps over multiple periods. */ - zero_samples = frames * sink->channels; + zero_samples = frames * audio_stream_get_channels(sink); if (num_ceps > 0) { zero_samples -= num_ceps + num_magic; w_ptr = mfcc_sink_copy_data_s16(sink, w_ptr, num_magic, (int16_t *)&magic); diff --git a/src/audio/mixer/mixer_generic.c b/src/audio/mixer/mixer_generic.c index 14c7430aee89..b8be3ecf63a1 100644 --- a/src/audio/mixer/mixer_generic.c +++ b/src/audio/mixer/mixer_generic.c @@ -21,12 +21,12 @@ static void mix_n_s16(struct comp_dev *dev, struct audio_stream __sparse_cache * int nmax; int i, j, n, ns; int processed = 0; - int nch = sink->channels; + int nch = audio_stream_get_channels(sink); int samples = frames * nch; - dest = sink->w_ptr; + dest = audio_stream_get_wptr(sink); for (j = 0; j < num_sources; j++) - src[j] = sources[j]->r_ptr; + src[j] = audio_stream_get_rptr(sources[j]); while (processed < samples) { nmax = samples - processed; @@ -68,12 +68,12 @@ static void mix_n_s24(struct comp_dev *dev, struct audio_stream __sparse_cache * int nmax; int i, j, n, ns; int processed = 0; - int nch = sink->channels; + int nch = audio_stream_get_channels(sink); int samples = frames * nch; - dest = sink->w_ptr; + dest = audio_stream_get_wptr(sink); for (j = 0; j < num_sources; j++) - src[j] = sources[j]->r_ptr; + src[j] = audio_stream_get_rptr(sources[j]); while (processed < samples) { nmax = samples - processed; @@ -115,12 +115,12 @@ static void mix_n_s32(struct comp_dev *dev, struct audio_stream __sparse_cache * int nmax; int i, j, n, ns; int processed = 0; - int nch = sink->channels; + int nch = audio_stream_get_channels(sink); int samples = frames * nch; - dest = sink->w_ptr; + dest = audio_stream_get_wptr(sink); for (j = 0; j < num_sources; j++) - src[j] = sources[j]->r_ptr; + src[j] = audio_stream_get_rptr(sources[j]); while (processed < samples) { nmax = samples - processed; diff --git a/src/audio/mixer/mixer_hifi3.c b/src/audio/mixer/mixer_hifi3.c index 0c237519ed61..3147ce0a35b6 100644 --- a/src/audio/mixer/mixer_hifi3.c +++ b/src/audio/mixer/mixer_hifi3.c @@ -18,7 +18,7 @@ static void mix_n_s16(struct comp_dev *dev, struct audio_stream __sparse_cache * uint32_t frames) { ae_int16x4 * in[PLATFORM_MAX_CHANNELS]; - ae_int16x4 *out = sink->w_ptr; + ae_int16x4 *out = audio_stream_get_wptr(sink); ae_int16x4 sample = AE_ZERO16(); ae_int16x4 res = AE_ZERO16(); ae_int32x2 val1; @@ -26,11 +26,11 @@ static void mix_n_s16(struct comp_dev *dev, struct audio_stream __sparse_cache * ae_int32x2 sample_1; ae_int32x2 sample_2; unsigned int n, m, nmax, i, j, left_samples; - unsigned int samples = frames * sink->channels; + unsigned int samples = frames * audio_stream_get_channels(sink); + + for (j = 0; j < num_sources; j++) + in[j] = audio_stream_get_rptr(sources[j]); - for (j = 0; j < num_sources; j++) { - in[j] = sources[j]->r_ptr; - } for (left_samples = samples; left_samples; left_samples -= n) { out = audio_stream_wrap(sink, out); nmax = audio_stream_samples_without_wrap_s16(sink, out); @@ -74,15 +74,15 @@ static void mix_n_s24(struct comp_dev *dev, struct audio_stream __sparse_cache * uint32_t frames) { ae_int32x2 *in[PLATFORM_MAX_CHANNELS]; - ae_int32x2 *out = sink->w_ptr; + ae_int32x2 *out = audio_stream_get_wptr(sink); ae_int32x2 val; ae_int32x2 sample = AE_ZERO32(); unsigned int n, m, nmax, i, j, left_samples; - unsigned int samples = frames * sink->channels; + unsigned int samples = frames * audio_stream_get_channels(sink); + + for (j = 0; j < num_sources; j++) + in[j] = audio_stream_get_rptr(sources[j]); - for (j = 0; j < num_sources; j++) { - in[j] = sources[j]->r_ptr; - } for (left_samples = samples; left_samples; left_samples -= n) { out = audio_stream_wrap(sink, out); nmax = audio_stream_samples_without_wrap_s32(sink, out); @@ -119,16 +119,16 @@ static void mix_n_s32(struct comp_dev *dev, struct audio_stream __sparse_cache * uint32_t frames) { ae_q32s * in[PLATFORM_MAX_CHANNELS]; - ae_int32 *out = sink->w_ptr; + ae_int32 *out = audio_stream_get_wptr(sink); ae_int64 sample; ae_int64 val; ae_int32x2 res; unsigned int n, nmax, i, j, left_samples; unsigned int m = 0; - unsigned int samples = frames * sink->channels; + unsigned int samples = frames * audio_stream_get_channels(sink); for (j = 0; j < num_sources; j++) - in[j] = sources[j]->r_ptr; + in[j] = audio_stream_get_rptr(sources[j]); for (left_samples = samples; left_samples; left_samples -= n) { out = audio_stream_wrap(sink, out); diff --git a/src/audio/mixin_mixout/mixin_mixout.c b/src/audio/mixin_mixout/mixin_mixout.c index f549e631ba22..0c68d80dd6f5 100644 --- a/src/audio/mixin_mixout/mixin_mixout.c +++ b/src/audio/mixin_mixout/mixin_mixout.c @@ -100,7 +100,7 @@ static int mixin_init(struct processing_module *mod) struct comp_dev *dev = mod->dev; struct mixin_data *md; int i; - enum sof_ipc_frame __sparse_cache frame_fmt, valid_fmt; + enum sof_ipc_frame frame_fmt, valid_fmt; comp_dbg(dev, "mixin_init()"); @@ -132,7 +132,7 @@ static int mixout_init(struct processing_module *mod) struct module_source_info __sparse_cache *mod_source_info; struct comp_dev *dev = mod->dev; struct mixout_data *mo_data; - enum sof_ipc_frame __sparse_cache frame_fmt, valid_fmt; + enum sof_ipc_frame frame_fmt, valid_fmt; comp_dbg(dev, "mixout_new()"); @@ -202,13 +202,15 @@ static int mix_and_remap(struct comp_dev *dev, const struct mixin_data *mixin_da * channel count is passed as 1, channel index is 0, frame indices (start_frame * and mixed_frame) and frame count are multiplied by real stream channel count. */ - mixin_data->normal_mix_channel(sink, start_frame * sink->channels, - mixed_frames * sink->channels, source, - frame_count * sink->channels, sink_config->gain); + mixin_data->normal_mix_channel(sink, start_frame * audio_stream_get_channels(sink), + mixed_frames * audio_stream_get_channels(sink), + source, + frame_count * audio_stream_get_channels(sink), + sink_config->gain); } else if (sink_config->mixer_mode == IPC4_MIXER_CHANNEL_REMAPPING_MODE) { int i; - for (i = 0; i < sink->channels; i++) { + for (i = 0; i < audio_stream_get_channels(sink); i++) { uint8_t source_channel = (sink_config->output_channel_map >> (i * 4)) & 0xf; @@ -216,16 +218,18 @@ static int mix_and_remap(struct comp_dev *dev, const struct mixin_data *mixin_da mixin_data->mute_channel(sink, i, start_frame, mixed_frames, frame_count); } else { - if (source_channel >= source->channels) { + if (source_channel >= audio_stream_get_channels(source)) { comp_err(dev, "Out of range chmap: 0x%x, src channels: %u", sink_config->output_channel_map, - source->channels); + audio_stream_get_channels(source)); return -EINVAL; } - mixin_data->remap_mix_channel(sink, i, sink->channels, start_frame, - mixed_frames, source, source_channel, - source->channels, frame_count, - sink_config->gain); + mixin_data->remap_mix_channel(sink, i, + audio_stream_get_channels(sink), + start_frame, mixed_frames, + source, source_channel, + audio_stream_get_channels(source), + frame_count, sink_config->gain); } } } else { @@ -252,7 +256,8 @@ static void silence(struct audio_stream __sparse_cache *stream, uint32_t start_f return; size = audio_stream_period_bytes(stream, frame_count - skip_mixed_frames); - ptr = (uint8_t *)stream->w_ptr + audio_stream_period_bytes(stream, mixed_frames); + ptr = (uint8_t *)audio_stream_get_wptr(stream) + + audio_stream_period_bytes(stream, mixed_frames); while (size) { ptr = audio_stream_wrap(stream, ptr); @@ -628,12 +633,14 @@ static int mixin_params(struct processing_module *mod) list_for_item(blist, &dev->bsink_list) { struct comp_buffer *sink; struct comp_buffer __sparse_cache *sink_c; + enum sof_ipc_frame frame_fmt, valid_fmt; uint16_t sink_id; sink = buffer_from_list(blist, PPL_DIR_DOWNSTREAM); sink_c = buffer_acquire(sink); - sink_c->stream.channels = mod->priv.cfg.base_cfg.audio_fmt.channels_count; + audio_stream_set_channels(&sink_c->stream, + mod->priv.cfg.base_cfg.audio_fmt.channels_count); /* Applying channel remapping may produce sink stream with channel count * different from source channel count. @@ -646,17 +653,20 @@ static int mixin_params(struct processing_module *mod) return -EINVAL; } if (md->sink_config[sink_id].mixer_mode == IPC4_MIXER_CHANNEL_REMAPPING_MODE) - sink_c->stream.channels = md->sink_config[sink_id].output_channel_count; + audio_stream_set_channels(&sink_c->stream, + md->sink_config[sink_id].output_channel_count); /* comp_verify_params() does not modify valid_sample_fmt (a BUG?), * let's do this here */ audio_stream_fmt_conversion(mod->priv.cfg.base_cfg.audio_fmt.depth, mod->priv.cfg.base_cfg.audio_fmt.valid_bit_depth, - &sink_c->stream.frame_fmt, - &sink_c->stream.valid_sample_fmt, + &frame_fmt, &valid_fmt, mod->priv.cfg.base_cfg.audio_fmt.s_type); + audio_stream_set_frm_fmt(&sink_c->stream, frame_fmt); + audio_stream_set_valid_fmt(&sink_c->stream, valid_fmt); + buffer_release(sink_c); } @@ -695,7 +705,7 @@ static int mixin_prepare(struct processing_module *mod) sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); sink_c = buffer_acquire(sink); - fmt = sink_c->stream.valid_sample_fmt; + fmt = audio_stream_get_valid_fmt(&sink_c->stream); buffer_release(sink_c); /* currently inactive so setup mixer */ @@ -723,7 +733,7 @@ static int mixin_prepare(struct processing_module *mod) static void base_module_cfg_to_stream_params(const struct ipc4_base_module_cfg *base_cfg, struct sof_ipc_stream_params *params) { - enum sof_ipc_frame __sparse_cache frame_fmt, valid_fmt; + enum sof_ipc_frame frame_fmt, valid_fmt; int i; memset(params, 0, sizeof(struct sof_ipc_stream_params)); @@ -750,7 +760,7 @@ static int mixout_params(struct processing_module *mod) struct comp_buffer *sink; struct comp_buffer __sparse_cache *sink_c; struct comp_dev *dev = mod->dev; - enum sof_ipc_frame __sparse_cache dummy; + enum sof_ipc_frame frame_fmt, valid_fmt; uint32_t sink_period_bytes, sink_stream_size; int ret; @@ -770,10 +780,12 @@ static int mixout_params(struct processing_module *mod) /* comp_verify_params() does not modify valid_sample_fmt (a BUG?), let's do this here */ audio_stream_fmt_conversion(mod->priv.cfg.base_cfg.audio_fmt.depth, mod->priv.cfg.base_cfg.audio_fmt.valid_bit_depth, - &dummy, &sink_c->stream.valid_sample_fmt, + &frame_fmt, &valid_fmt, mod->priv.cfg.base_cfg.audio_fmt.s_type); - sink_stream_size = sink_c->stream.size; + audio_stream_set_valid_fmt(&sink_c->stream, valid_fmt); + + sink_stream_size = audio_stream_get_size(&sink_c->stream); /* calculate period size based on config */ sink_period_bytes = audio_stream_period_bytes(&sink_c->stream, diff --git a/src/audio/mixin_mixout/mixin_mixout_generic.c b/src/audio/mixin_mixout/mixin_mixout_generic.c index d316597b4723..01b7ce11aec1 100644 --- a/src/audio/mixin_mixout/mixin_mixout_generic.c +++ b/src/audio/mixin_mixout/mixin_mixout_generic.c @@ -11,9 +11,9 @@ #ifdef MIXIN_MIXOUT_GENERIC #if CONFIG_FORMAT_S16LE -/* Instead of using sink->channels and source->channels, sink_channel_count and - * source_channel_count are supplied as parameters. This is done to reuse the function - * to also mix an entire stream. In this case the function is called with fake stream +/* Instead of using audio_stream_get_channels(sink) and audio_stream_get_channels(source), + * sink_channel_count and source_channel_count are supplied as parameters. This is done to reuse + * the function to also mix an entire stream. In this case the function is called with fake stream * parameters: multichannel stream is treated as single channel and so the entire stream * contents is mixed. */ @@ -26,8 +26,8 @@ static void normal_mix_channel_s16(struct audio_stream __sparse_cache *sink, int int32_t n, nmax, i; /* audio_stream_wrap() is required and is done below in a loop */ - int16_t *dst = (int16_t *)sink->w_ptr + start_frame; - int16_t *src = (int16_t *)source->r_ptr; + int16_t *dst = (int16_t *)audio_stream_get_wptr(sink) + start_frame; + int16_t *src = audio_stream_get_rptr(source); assert(mixed_frames >= start_frame); frames_to_mix = mixed_frames - start_frame; @@ -56,6 +56,8 @@ static void normal_mix_channel_s16(struct audio_stream __sparse_cache *sink, int nmax = audio_stream_samples_without_wrap_s16(sink, dst); n = MIN(n, nmax); memcpy_s(dst, n * sizeof(int16_t), src, n * sizeof(int16_t)); + dst += n; + src += n; } } @@ -71,8 +73,9 @@ static void remap_mix_channel_s16(struct audio_stream __sparse_cache *sink, int32_t n, nmax, frames, i, samples; /* audio_stream_wrap() is required and is done below in a loop */ - dst = (int16_t *)sink->w_ptr + start_frame * sink_channel_count + sink_channel_index; - src = (int16_t *)source->r_ptr + source_channel_index; + dst = (int16_t *)audio_stream_get_wptr(sink) + start_frame * sink_channel_count + + sink_channel_index; + src = (int16_t *)audio_stream_get_rptr(source) + source_channel_index; assert(mixed_frames >= start_frame); frames_to_mix = mixed_frames - start_frame; @@ -129,9 +132,11 @@ static void mute_channel_s16(struct audio_stream __sparse_cache *stream, int32_t if (frame_count <= skip_mixed_frames) return; frame_count -= skip_mixed_frames; - channel_count = stream->channels; + channel_count = audio_stream_get_channels(stream); /* audio_stream_wrap() is needed here and it is just below in a loop */ - ptr = (int16_t *)stream->w_ptr + mixed_frames * stream->channels + channel_index; + ptr = (int16_t *)audio_stream_get_wptr(stream) + + mixed_frames * audio_stream_get_channels(stream) + + channel_index; for (left_frames = frame_count; left_frames; left_frames -= frames) { ptr = audio_stream_wrap(stream, ptr); @@ -149,9 +154,9 @@ static void mute_channel_s16(struct audio_stream __sparse_cache *stream, int32_t #endif /* CONFIG_FORMAT_S16LE */ #if CONFIG_FORMAT_S24LE -/* Instead of using sink->channels and source->channels, sink_channel_count and - * source_channel_count are supplied as parameters. This is done to reuse the function - * to also mix an entire stream. In this case the function is called with fake stream +/* Instead of using audio_stream_get_channels(sink) and audio_stream_get_channels(source), + * sink_channel_count and source_channel_count are supplied as parameters. This is done to reuse + * the function to also mix an entire stream. In this case the function is called with fake stream * parameters: multichannel stream is treated as single channel and so the entire stream * contents is mixed. */ @@ -163,8 +168,8 @@ static void normal_mix_channel_s24(struct audio_stream __sparse_cache *sink, int int32_t frames_to_mix, frames_to_copy, left_frames; int32_t n, nmax, i; /* audio_stream_wrap() is required and is done below in a loop */ - int32_t *dst = (int32_t *)sink->w_ptr + start_frame; - int32_t *src = (int32_t *)source->r_ptr; + int32_t *dst = (int32_t *)audio_stream_get_wptr(sink) + start_frame; + int32_t *src = audio_stream_get_rptr(source); assert(mixed_frames >= start_frame); frames_to_mix = mixed_frames - start_frame; @@ -193,6 +198,8 @@ static void normal_mix_channel_s24(struct audio_stream __sparse_cache *sink, int nmax = audio_stream_samples_without_wrap_s24(sink, dst); n = MIN(n, nmax); memcpy_s(dst, n * sizeof(int32_t), src, n * sizeof(int32_t)); + dst += n; + src += n; } } @@ -208,8 +215,9 @@ static void remap_mix_channel_s24(struct audio_stream __sparse_cache *sink, int32_t n, nmax, i, frames, samples; /* audio_stream_wrap() is required and is done below in a loop */ - dst = (int32_t *)sink->w_ptr + start_frame * sink_channel_count + sink_channel_index; - src = (int32_t *)source->r_ptr + source_channel_index; + dst = (int32_t *)audio_stream_get_wptr(sink) + start_frame * sink_channel_count + + sink_channel_index; + src = (int32_t *)audio_stream_get_rptr(source) + source_channel_index; assert(mixed_frames >= start_frame); frames_to_mix = mixed_frames - start_frame; @@ -259,9 +267,9 @@ static void remap_mix_channel_s24(struct audio_stream __sparse_cache *sink, #endif /* CONFIG_FORMAT_S24LE */ #if CONFIG_FORMAT_S32LE -/* Instead of using sink->channels and source->channels, sink_channel_count and - * source_channel_count are supplied as parameters. This is done to reuse the function - * to also mix an entire stream. In this case the function is called with fake stream +/* Instead of using audio_stream_get_channels(sink) and audio_stream_get_channels(source), + * sink_channel_count and source_channel_count are supplied as parameters. This is done to reuse + * the function to also mix an entire stream. In this case the function is called with fake stream * parameters: multichannel stream is treated as single channel and so the entire stream * contents is mixed. */ @@ -272,8 +280,8 @@ static void normal_mix_channel_s32(struct audio_stream __sparse_cache *sink, int { int32_t frames_to_mix, frames_to_copy, left_frames; int32_t n, nmax, i; - int32_t *dst = (int32_t *)sink->w_ptr + start_frame; - int32_t *src = (int32_t *)source->r_ptr; + int32_t *dst = (int32_t *)audio_stream_get_wptr(sink) + start_frame; + int32_t *src = audio_stream_get_rptr(source); assert(mixed_frames >= start_frame); frames_to_mix = mixed_frames - start_frame; @@ -302,6 +310,8 @@ static void normal_mix_channel_s32(struct audio_stream __sparse_cache *sink, int nmax = audio_stream_samples_without_wrap_s32(sink, dst); n = MIN(n, nmax); memcpy_s(dst, n * sizeof(int32_t), src, n * sizeof(int32_t)); + dst += n; + src += n; } } @@ -317,8 +327,9 @@ static void remap_mix_channel_s32(struct audio_stream __sparse_cache *sink, int32_t *dst, *src; /* audio_stream_wrap() is required and is done below in a loop */ - dst = (int32_t *)sink->w_ptr + start_frame * sink_channel_count + sink_channel_index; - src = (int32_t *)source->r_ptr + source_channel_index; + dst = (int32_t *)audio_stream_get_wptr(sink) + start_frame * sink_channel_count + + sink_channel_index; + src = (int32_t *)audio_stream_get_rptr(source) + source_channel_index; assert(mixed_frames >= start_frame); frames_to_mix = mixed_frames - start_frame; @@ -378,9 +389,11 @@ static void mute_channel_s32(struct audio_stream __sparse_cache *stream, int32_t if (frame_count <= skip_mixed_frames) return; frame_count -= skip_mixed_frames; - channel_count = stream->channels; + channel_count = audio_stream_get_channels(stream); - ptr = (int32_t *)stream->w_ptr + mixed_frames * stream->channels + channel_index; + ptr = (int32_t *)audio_stream_get_wptr(stream) + + mixed_frames * audio_stream_get_channels(stream) + + channel_index; for (left_frames = frame_count; left_frames > 0; left_frames -= frames) { ptr = audio_stream_wrap(stream, ptr); diff --git a/src/audio/mixin_mixout/mixin_mixout_hifi3.c b/src/audio/mixin_mixout/mixin_mixout_hifi3.c index 662032de3a60..1230f7fa761c 100644 --- a/src/audio/mixin_mixout/mixin_mixout_hifi3.c +++ b/src/audio/mixin_mixout/mixin_mixout_hifi3.c @@ -10,9 +10,9 @@ #ifdef MIXIN_MIXOUT_HIFI3 #if CONFIG_FORMAT_S16LE -/* Instead of using sink->channels and source->channels, sink_channel_count and - * source_channel_count are supplied as parameters. This is done to reuse the function - * to also mix an entire stream. In this case the function is called with fake stream +/* Instead of using audio_stream_get_channels(sink) and audio_stream_get_channels(source), + * sink_channel_count and source_channel_count are supplied as parameters. This is done to reuse + * the function to also mix an entire stream. In this case the function is called with fake stream * parameters: multichannel stream is treated as single channel and so the entire stream * contents is mixed. */ @@ -31,8 +31,8 @@ static void normal_mix_channel_s16(struct audio_stream __sparse_cache *sink, int ae_valign outu1 = AE_ZALIGN64(); ae_valign outu2 = AE_ZALIGN64(); /* audio_stream_wrap() is required and is done below in a loop */ - ae_int16 *dst = (ae_int16 *)sink->w_ptr + start_frame; - ae_int16 *src = (ae_int16 *)source->r_ptr; + ae_int16 *dst = (ae_int16 *)audio_stream_get_wptr(sink) + start_frame; + ae_int16 *src = audio_stream_get_rptr(source); assert(mixed_frames >= start_frame); frames_to_mix = AE_MIN_32_signed(mixed_frames - start_frame, frame_count); @@ -122,8 +122,9 @@ static void remap_mix_channel_s16(struct audio_stream __sparse_cache *sink, ae_int16x4 gain_v; ae_int32x2 temp, out1; - dst = (ae_int16 *)sink->w_ptr + start_frame * sink_channel_count + sink_channel_index; - src = (ae_int16 *)source->r_ptr + source_channel_index; + dst = (ae_int16 *)audio_stream_get_wptr(sink) + start_frame * sink_channel_count + + sink_channel_index; + src = (ae_int16 *)audio_stream_get_rptr(source) + source_channel_index; src = audio_stream_wrap(source, src); assert(mixed_frames >= start_frame); @@ -134,8 +135,8 @@ static void remap_mix_channel_s16(struct audio_stream __sparse_cache *sink, AE_L16_IP(gain_v, pgain, 0); /* set source as circular buffer, hifi3 only have 1 circular buffer*/ - AE_SETCBEGIN0(source->addr); - AE_SETCEND0(source->end_addr); + AE_SETCBEGIN0(audio_stream_get_addr(source)); + AE_SETCEND0(audio_stream_get_end_addr(source)); for (left_frames = frames_to_mix; left_frames > 0; left_frames -= frames) { /* audio_stream_wrap() is required and is done below in a loop */ @@ -185,7 +186,7 @@ static void mute_channel_s16(struct audio_stream __sparse_cache *stream, int32_t int32_t start_frame, int32_t mixed_frames, int32_t frame_count) { int skip_mixed_frames, left_frames; - int off = stream->channels * sizeof(ae_int16); + int off = audio_stream_get_channels(stream) * sizeof(ae_int16); ae_int16 *ptr; ae_int16x4 zero = AE_ZERO16(); @@ -196,11 +197,13 @@ static void mute_channel_s16(struct audio_stream __sparse_cache *stream, int32_t return; frame_count -= skip_mixed_frames; - AE_SETCBEGIN0(stream->addr); - AE_SETCEND0(stream->end_addr); + AE_SETCBEGIN0(audio_stream_get_addr(stream)); + AE_SETCEND0(audio_stream_get_end_addr(stream)); /* audio_stream_wrap() is needed here and it is just below in a loop */ - ptr = (ae_int16 *)stream->w_ptr + mixed_frames * stream->channels + channel_index; + ptr = (ae_int16 *)audio_stream_get_wptr(stream) + + mixed_frames * audio_stream_get_channels(stream) + + channel_index; ptr = audio_stream_wrap(stream, ptr); for (left_frames = frame_count ; left_frames; left_frames--) @@ -209,9 +212,9 @@ static void mute_channel_s16(struct audio_stream __sparse_cache *stream, int32_t #endif /* CONFIG_FORMAT_S16LE */ #if CONFIG_FORMAT_S24LE -/* Instead of using sink->channels and source->channels, sink_channel_count and - * source_channel_count are supplied as parameters. This is done to reuse the function - * to also mix an entire stream. In this case the function is called with fake stream +/* Instead of using audio_stream_get_channels(sink) and audio_stream_get_channels(source), + * sink_channel_count and source_channel_count are supplied as parameters. This is done to reuse + * the function to also mix an entire stream. In this case the function is called with fake stream * parameters: multichannel stream is treated as single channel and so the entire stream * contents is mixed. */ @@ -230,8 +233,8 @@ static void normal_mix_channel_s24(struct audio_stream __sparse_cache *sink, int ae_valign outu1 = AE_ZALIGN64(); ae_valign outu2 = AE_ZALIGN64(); /* audio_stream_wrap() is required and is done below in a loop */ - int32_t *dst = (int32_t *)sink->w_ptr + start_frame; - int32_t *src = (int32_t *)source->r_ptr; + int32_t *dst = (int32_t *)audio_stream_get_wptr(sink) + start_frame; + int32_t *src = audio_stream_get_rptr(source); assert(mixed_frames >= start_frame); frames_to_mix = AE_MIN_32_signed(mixed_frames - start_frame, frame_count); @@ -314,8 +317,9 @@ static void remap_mix_channel_s24(struct audio_stream __sparse_cache *sink, ae_int16x4 gain_v; ae_int32 *dst, *src; - dst = (ae_int32 *)sink->w_ptr + start_frame * sink_channel_count + sink_channel_index; - src = (ae_int32 *)source->r_ptr + source_channel_index; + dst = (ae_int32 *)audio_stream_get_wptr(sink) + start_frame * sink_channel_count + + sink_channel_index; + src = (ae_int32 *)audio_stream_get_rptr(source) + source_channel_index; src = audio_stream_wrap(source, src); assert(mixed_frames >= start_frame); frames_to_mix = AE_MIN_32_signed(mixed_frames - start_frame, frame_count); @@ -324,8 +328,8 @@ static void remap_mix_channel_s24(struct audio_stream __sparse_cache *sink, /* store gain to a AE_DR register gain_v*/ AE_L16_IP(gain_v, pgain, 0); /* set source as circular buffer, hifi3 only have 1 circular buffer*/ - AE_SETCBEGIN0(source->addr); - AE_SETCEND0(source->end_addr); + AE_SETCBEGIN0(audio_stream_get_addr(source)); + AE_SETCEND0(audio_stream_get_end_addr(source)); for (left_frames = frames_to_mix; left_frames > 0; left_frames -= frames) { dst = audio_stream_wrap(sink, dst); @@ -379,9 +383,9 @@ static void remap_mix_channel_s24(struct audio_stream __sparse_cache *sink, #endif /* CONFIG_FORMAT_S24LE */ #if CONFIG_FORMAT_S32LE -/* Instead of using sink->channels and source->channels, sink_channel_count and - * source_channel_count are supplied as parameters. This is done to reuse the function - * to also mix an entire stream. In this case the function is called with fake stream +/* Instead of using audio_stream_get_channels(sink) and audio_stream_get_channels(source), + * sink_channel_count and source_channel_count are supplied as parameters. This is done to reuse + * the function to also mix an entire stream. In this case the function is called with fake stream * parameters: multichannel stream is treated as single channel and so the entire stream * contents is mixed. */ @@ -400,8 +404,8 @@ static void normal_mix_channel_s32(struct audio_stream __sparse_cache *sink, int ae_valign outu1 = AE_ZALIGN64(); ae_valign outu2 = AE_ZALIGN64(); /* audio_stream_wrap() is required and is done below in a loop */ - int32_t *dst = (int32_t *)sink->w_ptr + start_frame; - int32_t *src = (int32_t *)source->r_ptr; + int32_t *dst = (int32_t *)audio_stream_get_wptr(sink) + start_frame; + int32_t *src = audio_stream_get_rptr(source); assert(mixed_frames >= start_frame); frames_to_mix = AE_MIN_32_signed(mixed_frames - start_frame, frame_count); @@ -486,8 +490,9 @@ static void remap_mix_channel_s32(struct audio_stream __sparse_cache *sink, ae_int32 *dst, *src; /* audio_stream_wrap() is required and is done below in a loop */ - dst = (ae_int32 *)sink->w_ptr + start_frame * sink_channel_count + sink_channel_index; - src = (ae_int32 *)source->r_ptr + source_channel_index; + dst = (ae_int32 *)audio_stream_get_wptr(sink) + start_frame * sink_channel_count + + sink_channel_index; + src = (ae_int32 *)audio_stream_get_rptr(source) + source_channel_index; assert(mixed_frames >= start_frame); frames_to_mix = AE_MIN_32_signed(mixed_frames - start_frame, frame_count); @@ -495,8 +500,8 @@ static void remap_mix_channel_s32(struct audio_stream __sparse_cache *sink, /* store gain to a AE_DR register gain_v*/ AE_L16_IP(gain_v, pgain, 0); /* set source as circular buffer, hifi3 only have 1 circular buffer*/ - AE_SETCBEGIN0(source->addr); - AE_SETCEND0(source->end_addr); + AE_SETCBEGIN0(audio_stream_get_addr(source)); + AE_SETCEND0(audio_stream_get_end_addr(source)); src = audio_stream_wrap(source, src); for (left_frames = frames_to_mix; left_frames > 0; left_frames -= frames) { @@ -549,7 +554,7 @@ static void mute_channel_s32(struct audio_stream __sparse_cache *stream, int32_t { int skip_mixed_frames, left_frames; ae_int32 *ptr; - int off = stream->channels * sizeof(ae_int32); + int off = audio_stream_get_channels(stream) * sizeof(ae_int32); ae_int32x2 zero = AE_ZERO32(); assert(mixed_frames >= start_frame); @@ -559,11 +564,13 @@ static void mute_channel_s32(struct audio_stream __sparse_cache *stream, int32_t return; frame_count -= skip_mixed_frames; - AE_SETCBEGIN0(stream->addr); - AE_SETCEND0(stream->end_addr); + AE_SETCBEGIN0(audio_stream_get_addr(stream)); + AE_SETCEND0(audio_stream_get_end_addr(stream)); /* audio_stream_wrap() is needed here and it is just below in a loop */ - ptr = (ae_int32 *)stream->w_ptr + mixed_frames * stream->channels + channel_index; + ptr = (ae_int32 *)audio_stream_get_wptr(stream) + + mixed_frames * audio_stream_get_channels(stream) + + channel_index; ptr = audio_stream_wrap(stream, ptr); for (left_frames = frame_count ; left_frames > 0; left_frames--) diff --git a/src/audio/module_adapter/module/cadence.c b/src/audio/module_adapter/module/cadence.c index 1d74fcd10637..853005a8ad3f 100644 --- a/src/audio/module_adapter/module/cadence.c +++ b/src/audio/module_adapter/module/cadence.c @@ -583,10 +583,11 @@ cadence_codec_process(struct processing_module *mod, struct output_stream_buffer *output_buffers, int num_output_buffers) { struct comp_buffer *local_buff; + struct comp_buffer __sparse_cache *buffer_c; struct comp_dev *dev = mod->dev; struct module_data *codec = &mod->priv; struct cadence_codec_data *cd = codec->private; - int output_bytes = cadence_codec_get_samples(mod) * + int free_bytes, output_bytes = cadence_codec_get_samples(mod) * mod->stream_params->sample_container_bytes * mod->stream_params->channels; uint32_t remaining = input_buffers[0].size; @@ -613,7 +614,10 @@ cadence_codec_process(struct processing_module *mod, /* do not proceed with processing if not enough free space left in the local buffer */ local_buff = list_first_item(&mod->sink_buffer_list, struct comp_buffer, sink_list); - if (local_buff->stream.free < output_bytes) + buffer_c = buffer_acquire(local_buff); + free_bytes = audio_stream_get_free(&buffer_c->stream); + buffer_release(buffer_c); + if (free_bytes < output_bytes) return -ENOSPC; /* Proceed only if we have enough data to fill the module buffer completely */ diff --git a/src/audio/module_adapter/module/dts.c b/src/audio/module_adapter/module/dts.c index 28840c342918..71e2589b4ab9 100644 --- a/src/audio/module_adapter/module/dts.c +++ b/src/audio/module_adapter/module/dts.c @@ -93,9 +93,9 @@ static int dts_effect_populate_buffer_configuration(struct comp_dev *dev, buffer_fmt = source_c->buffer_fmt; stream = &source_c->stream; - frame_fmt = stream->frame_fmt; - rate = stream->rate; - channels = stream->channels; + frame_fmt = audio_stream_get_frm_fmt(stream); + rate = audio_stream_get_rate(stream); + channels = audio_stream_get_channels(stream); buffer_release(source_c); @@ -315,11 +315,11 @@ static int dts_codec_apply_config(struct processing_module *mod) /* Check that config->data isn't invalid and has size greater than 0 */ config_header_size = sizeof(config->size) + sizeof(config->avail); if (config->size < config_header_size) { - comp_err(dev, "dts_codec_apply_config() config->data is invalid"); - return -EINVAL; + comp_warn(dev, "dts_codec_apply_config() config->data is invalid"); + return 0; } else if (config->size == config_header_size) { - comp_err(dev, "dts_codec_apply_config() size of config->data is 0"); - return -EINVAL; + comp_warn(dev, "dts_codec_apply_config() size of config->data is 0"); + return 0; } /* Calculate size of config->data */ @@ -436,10 +436,6 @@ dts_codec_set_configuration(struct processing_module *mod, uint32_t config_id, md->state < MODULE_INITIALIZED) return 0; - /* return if configuration size is 0 */ - if (!md->new_cfg_size) - return 0; - /* whole configuration received, apply it now */ ret = dts_codec_apply_config(mod); if (ret) { diff --git a/src/audio/module_adapter/module/generic.c b/src/audio/module_adapter/module/generic.c index d0ed1da9d46d..bde580b66054 100644 --- a/src/audio/module_adapter/module/generic.c +++ b/src/audio/module_adapter/module/generic.c @@ -271,8 +271,10 @@ int module_reset(struct processing_module *mod) ret = md->ops->reset(mod); if (ret) { - comp_err(mod->dev, "module_reset() error %d: module specific reset() failed for comp %d", - ret, dev_comp_id(mod->dev)); + 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; } @@ -347,9 +349,15 @@ int module_free(struct processing_module *mod) int module_set_configuration(struct processing_module *mod, uint32_t config_id, enum module_cfg_fragment_position pos, size_t data_offset_size, - const uint8_t *fragment, size_t fragment_size, uint8_t *response, + const uint8_t *fragment_in, size_t fragment_size, uint8_t *response, size_t response_size) { +#if CONFIG_IPC_MAJOR_3 + struct sof_ipc_ctrl_data *cdata = (struct sof_ipc_ctrl_data *)fragment_in; + const uint8_t *fragment = (const uint8_t *)cdata->data[0].data; +#elif CONFIG_IPC_MAJOR_4 + const uint8_t *fragment = fragment_in; +#endif struct module_data *md = &mod->priv; struct comp_dev *dev = mod->dev; size_t offset = 0; diff --git a/src/audio/module_adapter/module/volume/volume.c b/src/audio/module_adapter/module/volume/volume.c index 5a9903c80e77..84526f2c5fd2 100644 --- a/src/audio/module_adapter/module/volume/volume.c +++ b/src/audio/module_adapter/module/volume/volume.c @@ -80,11 +80,11 @@ static uint32_t vol_zc_get_s16(const struct audio_stream __sparse_cache *source, { uint32_t curr_frames = frames; int32_t sum; - int16_t *x = source->r_ptr; + int16_t *x = audio_stream_get_rptr(source); int bytes; int nmax; int i, j, n; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; x = audio_stream_wrap(source, x + remaining_samples - 1); /* Go to last channel */ @@ -128,11 +128,11 @@ static uint32_t vol_zc_get_s24(const struct audio_stream __sparse_cache *source, { int64_t sum; uint32_t curr_frames = frames; - int32_t *x = source->r_ptr; + int32_t *x = audio_stream_get_rptr(source); int bytes; int nmax; int i, j, n; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; x = audio_stream_wrap(source, x + remaining_samples - 1); /* Go to last channel */ @@ -176,11 +176,11 @@ static uint32_t vol_zc_get_s32(const struct audio_stream __sparse_cache *source, { int64_t sum; uint32_t curr_frames = frames; - int32_t *x = source->r_ptr; + int32_t *x = audio_stream_get_rptr(source); int bytes; int nmax; int i, j, n; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; x = audio_stream_wrap(source, x + remaining_samples - 1); /* Go to last channel */ @@ -499,13 +499,7 @@ static int set_volume_ipc4(struct vol_data *cd, uint32_t const channel, */ static inline uint32_t convert_volume_ipc4_to_ipc3(struct comp_dev *dev, uint32_t volume) { - /* Limit received volume gain to MIN..MAX range before applying it. - * MAX is needed for now for the generic C gain arithmetics to prevent - * multiplication overflow with the 32 bit value. Non-zero MIN option - * can be useful to prevent totally muted small volume gain. - */ - - return sat_int24(Q_SHIFT_RND(volume, 31, 23)); + return sat_int32(Q_SHIFT_RND((int64_t)volume, 31, VOL_QXY_Y)); } static inline uint32_t convert_volume_ipc3_to_ipc4(uint32_t volume) @@ -513,7 +507,7 @@ static inline uint32_t convert_volume_ipc3_to_ipc4(uint32_t volume) /* In IPC4 volume is converted into Q1.23 format to be processed by firmware. * Now convert it back to Q1.31 */ - return sat_int32(Q_SHIFT_LEFT((int64_t)volume, 23, 31)); + return sat_int32(Q_SHIFT_LEFT((int64_t)volume, VOL_QXY_Y, 31)); } static inline void init_ramp(struct vol_data *cd, uint32_t curve_duration, uint32_t target_volume) @@ -985,10 +979,9 @@ static int volume_set_attenuation(struct processing_module *mod, const uint8_t * int data_size) { struct vol_data *cd = module_get_private_data(mod); + enum sof_ipc_frame frame_fmt, valid_fmt; struct comp_dev *dev = mod->dev; uint32_t attenuation; - uint32_t __sparse_cache valid_fmt, frame_fmt; - /* only support attenuation in format of 32bit */ if (data_size > sizeof(uint32_t)) { @@ -1088,10 +1081,10 @@ static int volume_params(struct processing_module *mod) { struct sof_ipc_stream_params *params = mod->stream_params; struct sof_ipc_stream_params vol_params; + enum sof_ipc_frame frame_fmt, valid_fmt; struct comp_dev *dev = mod->dev; struct comp_buffer *sinkb; struct comp_buffer __sparse_cache *sink_c; - uint32_t __sparse_cache valid_fmt, frame_fmt; int i, ret; comp_dbg(dev, "volume_params()"); @@ -1191,7 +1184,7 @@ static vol_zc_func vol_get_zc_function(struct comp_dev *dev, /* map the zc function to frame format */ for (i = 0; i < ARRAY_SIZE(zc_func_map); i++) { - if (sinkb->stream.valid_sample_fmt == zc_func_map[i].frame_fmt) + if (audio_stream_get_valid_fmt(&sinkb->stream) == zc_func_map[i].frame_fmt) return zc_func_map[i].func; } @@ -1276,9 +1269,9 @@ static int volume_prepare(struct processing_module *mod) sink_period_bytes = audio_stream_period_bytes(&sink_c->stream, dev->frames); - if (sink_c->stream.size < sink_period_bytes) { + if (audio_stream_get_size(&sink_c->stream) < sink_period_bytes) { comp_err(dev, "volume_prepare(): sink buffer size %d is insufficient < %d", - sink_c->stream.size, sink_period_bytes); + audio_stream_get_size(&sink_c->stream), sink_period_bytes); ret = -ENOMEM; goto err; } @@ -1306,13 +1299,14 @@ static int volume_prepare(struct processing_module *mod) */ cd->ramp_finished = false; - cd->channels = sink_c->stream.channels; + cd->channels = audio_stream_get_channels(&sink_c->stream); if (cd->channels > SOF_IPC_MAX_CHANNELS) { ret = -EINVAL; goto err; } - cd->sample_rate_inv = (int32_t)(1000LL * INT32_MAX / sink_c->stream.rate); + cd->sample_rate_inv = (int32_t)(1000LL * INT32_MAX / + audio_stream_get_rate(&sink_c->stream)); buffer_release(sink_c); diff --git a/src/audio/module_adapter/module/volume/volume_generic.c b/src/audio/module_adapter/module/volume/volume_generic.c index b4ba9a7002dd..893b27302aa7 100644 --- a/src/audio/module_adapter/module/volume/volume_generic.c +++ b/src/audio/module_adapter/module/volume/volume_generic.c @@ -67,11 +67,11 @@ static void vol_s24_to_s24(struct processing_module *mod, struct input_stream_bu int32_t *x, *x0; int32_t *y, *y0; int nmax, n, i, j; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; - x = audio_stream_wrap(source, (char *)source->r_ptr + bsource->consumed); - y = audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); + x = audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); + y = audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + bsink->size); bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(remaining_samples); bsink->size += VOL_S32_SAMPLES_TO_BYTES(remaining_samples); @@ -118,11 +118,11 @@ static void vol_s32_to_s32(struct processing_module *mod, struct input_stream_bu int32_t *x, *x0; int32_t *y, *y0; int nmax, n, i, j; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; - x = audio_stream_wrap(source, (char *)source->r_ptr + bsource->consumed); - y = audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); + x = audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); + y = audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + bsink->size); bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(remaining_samples); bsink->size += VOL_S32_SAMPLES_TO_BYTES(remaining_samples); while (remaining_samples) { @@ -172,11 +172,11 @@ static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_bu int16_t *x, *x0; int16_t *y, *y0; int nmax, n, i, j; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; - x = audio_stream_wrap(source, (char *)source->r_ptr + bsource->consumed); - y = audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); + x = audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); + y = audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + bsink->size); bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(remaining_samples); bsink->size += VOL_S16_SAMPLES_TO_BYTES(remaining_samples); while (remaining_samples) { diff --git a/src/audio/module_adapter/module/volume/volume_generic_with_peakvol.c b/src/audio/module_adapter/module/volume/volume_generic_with_peakvol.c index 0a90933d0d75..87498c91f6dc 100644 --- a/src/audio/module_adapter/module/volume/volume_generic_with_peakvol.c +++ b/src/audio/module_adapter/module/volume/volume_generic_with_peakvol.c @@ -63,13 +63,13 @@ static void vol_s24_to_s24(struct processing_module *mod, struct input_stream_bu int32_t *x, *x0; int32_t *y, *y0; int nmax, n, i, j; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; int32_t tmp; memset(cd->peak_regs.peak_meter, 0, sizeof(uint32_t) * cd->channels); - x = audio_stream_wrap(source, (char *)source->r_ptr + bsource->consumed); - y = audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); + x = audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); + y = audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + bsink->size); bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(remaining_samples); bsink->size += VOL_S32_SAMPLES_TO_BYTES(remaining_samples); @@ -122,13 +122,13 @@ static void vol_s32_to_s32(struct processing_module *mod, struct input_stream_bu int32_t *x, *x0; int32_t *y, *y0; int nmax, n, i, j; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; int32_t tmp; memset(cd->peak_regs.peak_meter, 0, sizeof(uint32_t) * cd->channels); - x = audio_stream_wrap(source, (char *)source->r_ptr + bsource->consumed); - y = audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); + x = audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); + y = audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + bsink->size); bsource->consumed += VOL_S32_SAMPLES_TO_BYTES(remaining_samples); bsink->size += VOL_S32_SAMPLES_TO_BYTES(remaining_samples); while (remaining_samples) { @@ -185,13 +185,13 @@ static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_bu int16_t *x, *x0; int16_t *y, *y0; int nmax, n, i, j; - const int nch = source->channels; + const int nch = audio_stream_get_channels(source); int remaining_samples = frames * nch; int32_t tmp; memset(cd->peak_regs.peak_meter, 0, sizeof(uint32_t) * cd->channels); - x = audio_stream_wrap(source, (char *)source->r_ptr + bsource->consumed); - y = audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); + x = audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); + y = audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + bsink->size); bsource->consumed += VOL_S16_SAMPLES_TO_BYTES(remaining_samples); bsink->size += VOL_S16_SAMPLES_TO_BYTES(remaining_samples); diff --git a/src/audio/module_adapter/module/volume/volume_hifi3.c b/src/audio/module_adapter/module/volume/volume_hifi3.c index 291e8f6e04ac..c905ad5601dd 100644 --- a/src/audio/module_adapter/module/volume/volume_hifi3.c +++ b/src/audio/module_adapter/module/volume/volume_hifi3.c @@ -70,10 +70,11 @@ static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_strea ae_f32x2 *vol; ae_valign inu = AE_ZALIGN64(); ae_valign outu = AE_ZALIGN64(); - ae_f32x2 *in = (ae_f32x2 *)audio_stream_wrap(source, (char *)source->r_ptr + ae_f32x2 *in = (ae_f32x2 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); - ae_f32x2 *out = (ae_f32x2 *)audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); - const int channels_count = sink->channels; + ae_f32x2 *out = (ae_f32x2 *)audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + + bsink->size); + const int channels_count = audio_stream_get_channels(sink); const int inc = sizeof(ae_f32x2); int samples = channels_count * frames; @@ -159,12 +160,13 @@ static void vol_s32_to_s24_s32(struct processing_module *mod, struct input_strea ae_f32x2 *vol; ae_valign inu = AE_ZALIGN64(); ae_valign outu = AE_ZALIGN64(); - const int channels_count = sink->channels; + const int channels_count = audio_stream_get_channels(sink); const int inc = sizeof(ae_f32x2); int samples = channels_count * frames; - ae_f32x2 *in = (ae_f32x2 *)audio_stream_wrap(source, (char *)source->r_ptr + ae_f32x2 *in = (ae_f32x2 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); - ae_f32x2 *out = (ae_f32x2 *)audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); + ae_f32x2 *out = (ae_f32x2 *)audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + + bsink->size); /** to ensure the address is 8-byte aligned and avoid risk of * error loading of volume gain while the cd->vol would be set @@ -252,10 +254,11 @@ static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_bu ae_f32x2 *vol; ae_valign inu = AE_ZALIGN64(); ae_valign outu = AE_ZALIGN64(); - ae_f16x4 *in = (ae_f16x4 *)audio_stream_wrap(source, (char *)source->r_ptr + ae_f16x4 *in = (ae_f16x4 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); - ae_f16x4 *out = (ae_f16x4 *)audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); - const int channels_count = sink->channels; + ae_f16x4 *out = (ae_f16x4 *)audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + + bsink->size); + const int channels_count = audio_stream_get_channels(sink); const int inc = sizeof(ae_f32x2); int samples = channels_count * frames; diff --git a/src/audio/module_adapter/module/volume/volume_hifi3_with_peakvol.c b/src/audio/module_adapter/module/volume/volume_hifi3_with_peakvol.c index a9332991431d..ff9691429ba7 100644 --- a/src/audio/module_adapter/module/volume/volume_hifi3_with_peakvol.c +++ b/src/audio/module_adapter/module/volume/volume_hifi3_with_peakvol.c @@ -63,10 +63,11 @@ static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_strea ae_f32x2 *vol; ae_valign inu = AE_ZALIGN64(); ae_valign outu = AE_ZALIGN64(); - ae_f32x2 *in = (ae_f32x2 *)audio_stream_wrap(source, (char *)source->r_ptr + ae_f32x2 *in = (ae_f32x2 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); - ae_f32x2 *out = (ae_f32x2 *)audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); - const int channels_count = sink->channels; + ae_f32x2 *out = (ae_f32x2 *)audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + + bsink->size); + const int channels_count = audio_stream_get_channels(sink); const int inc = sizeof(ae_f32x2); int samples = channels_count * frames; ae_f32x2 temp; @@ -113,7 +114,7 @@ static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_strea #if COMP_VOLUME_Q8_16 out_sample = AE_MULFP32X2RS(AE_SLAI32S(volume, 7), AE_SLAI32(in_sample, 8)); #elif COMP_VOLUME_Q1_23 - out_sample = AE_MULFP32X2RS(volume, AE_SLAI32S(in_sample, 8)); + out_sample = AE_MULFP32X2RS(volume, AE_SLAI32(in_sample, 8)); #else #error "Need CONFIG_COMP_VOLUME_Qx_y" #endif @@ -165,12 +166,13 @@ static void vol_s32_to_s24_s32(struct processing_module *mod, struct input_strea ae_f32x2 *vol; ae_valign inu = AE_ZALIGN64(); ae_valign outu = AE_ZALIGN64(); - const int channels_count = sink->channels; + const int channels_count = audio_stream_get_channels(sink); const int inc = sizeof(ae_f32x2); int samples = channels_count * frames; - ae_f32x2 *in = (ae_f32x2 *)audio_stream_wrap(source, (char *)source->r_ptr + ae_f32x2 *in = (ae_f32x2 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); - ae_f32x2 *out = (ae_f32x2 *)audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); + ae_f32x2 *out = (ae_f32x2 *)audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + + bsink->size); ae_f32x2 temp; ae_f32x2 *peakvol = (ae_f32x2 *)cd->peak_vol; @@ -274,10 +276,11 @@ static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_bu ae_f32x2 *vol; ae_valign inu = AE_ZALIGN64(); ae_valign outu = AE_ZALIGN64(); - ae_f16x4 *in = (ae_f16x4 *)audio_stream_wrap(source, (char *)source->r_ptr + ae_f16x4 *in = (ae_f16x4 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); - ae_f16x4 *out = (ae_f16x4 *)audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); - const int channels_count = sink->channels; + ae_f16x4 *out = (ae_f16x4 *)audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + + bsink->size); + const int channels_count = audio_stream_get_channels(sink); const int inc = sizeof(ae_f32x2); int samples = channels_count * frames; ae_f32x2 temp; @@ -389,11 +392,12 @@ static void vol_s24_to_s24_s32(struct processing_module *mod, struct input_strea ae_f32x2 out_sample = AE_ZERO32(); ae_f32x2 volume = AE_ZERO32(); int channel, n, i, m; - ae_f32 *in0 = (ae_f32 *)audio_stream_wrap(source, (char *)source->r_ptr + ae_f32 *in0 = (ae_f32 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); - ae_f32 *out0 = (ae_f32 *)audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); + ae_f32 *out0 = (ae_f32 *)audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + + bsink->size); ae_f32 *in, *out; - const int channels_count = sink->channels; + const int channels_count = audio_stream_get_channels(sink); const int inc = sizeof(ae_f32) * channels_count; int samples = channels_count * frames; ae_f32x2 peak_vol; @@ -469,12 +473,13 @@ static void vol_s32_to_s24_s32(struct processing_module *mod, struct input_strea ae_f32x2 volume = AE_ZERO32(); int i, n, channel, m; ae_f64 mult0; - const int channels_count = sink->channels; + const int channels_count = audio_stream_get_channels(sink); const int inc = sizeof(ae_f32) * channels_count; int samples = channels_count * frames; - ae_f32 *in0 = (ae_f32 *)audio_stream_wrap(source, (char *)source->r_ptr + ae_f32 *in0 = (ae_f32 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); - ae_f32 *out0 = (ae_f32 *)audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); + ae_f32 *out0 = (ae_f32 *)audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + + bsink->size); ae_f32 *in, *out; ae_f32x2 peak_vol; uint32_t *peak_meter = cd->peak_regs.peak_meter; @@ -550,10 +555,11 @@ static void vol_s16_to_s16(struct processing_module *mod, struct input_stream_bu int i, n, channel, m; ae_f16 *in; ae_f16 *out; - ae_f16 *in0 = (ae_f16 *)audio_stream_wrap(source, (char *)source->r_ptr + ae_f16 *in0 = (ae_f16 *)audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + bsource->consumed); - ae_f16 *out0 = (ae_f16 *)audio_stream_wrap(sink, (char *)sink->w_ptr + bsink->size); - const int channels_count = sink->channels; + ae_f16 *out0 = (ae_f16 *)audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + + bsink->size); + const int channels_count = audio_stream_get_channels(sink); const int inc = sizeof(ae_f16) * channels_count; int samples = channels_count * frames; ae_f32x2 peak_vol; diff --git a/src/audio/module_adapter/module/waves.c b/src/audio/module_adapter/module/waves.c index bc86f57997f6..fa1613644599 100644 --- a/src/audio/module_adapter/module/waves.c +++ b/src/audio/module_adapter/module/waves.c @@ -235,25 +235,25 @@ static int waves_effect_check(struct comp_dev *dev) /* todo use fallback to comp_verify_params when ready */ /* resampling not supported */ - if (src_fmt->rate != snk_fmt->rate) { + if (src_fmt->rate != audio_stream_get_rate(snk_fmt)) { comp_err(dev, "waves_effect_check() source %d sink %d rate mismatch", - src_fmt->rate, snk_fmt->rate); + audio_stream_get_rate(src_fmt), audio_stream_get_rate(snk_fmt)); ret = -EINVAL; goto out; } /* upmix/downmix not supported */ - if (src_fmt->channels != snk_fmt->channels) { + if (src_fmt->channels != audio_stream_get_channels(snk_fmt)) { comp_err(dev, "waves_effect_check() source %d sink %d channels mismatch", - src_fmt->channels, snk_fmt->channels); + audio_stream_get_channels(src_fmt), audio_stream_get_channels(snk_fmt)); ret = -EINVAL; goto out; } /* different frame format not supported */ - if (src_fmt->frame_fmt != snk_fmt->frame_fmt) { + if (src_fmt->frame_fmt != audio_stream_get_frm_fmt(snk_fmt)) { comp_err(dev, "waves_effect_check() source %d sink %d sample format mismatch", - src_fmt->frame_fmt, snk_fmt->frame_fmt); + audio_stream_get_frm_fmt(src_fmt), audio_stream_get_frm_fmt(snk_fmt)); ret = -EINVAL; goto out; } @@ -265,7 +265,7 @@ static int waves_effect_check(struct comp_dev *dev) goto out; } - if (!format_is_supported(src_fmt->frame_fmt)) { + if (!format_is_supported(audio_stream_get_frm_fmt(src_fmt))) { comp_err(dev, "waves_effect_check() float samples not supported"); ret = -EINVAL; goto out; @@ -277,14 +277,16 @@ static int waves_effect_check(struct comp_dev *dev) goto out; } - if (!rate_is_supported(src_fmt->rate)) { - comp_err(dev, "waves_effect_check() rate %d not supported", src_fmt->rate); + if (!rate_is_supported(audio_stream_get_rate(src_fmt))) { + comp_err(dev, "waves_effect_check() rate %d not supported", + audio_stream_get_rate(src_fmt)); ret = -EINVAL; goto out; } if (src_fmt->channels != 2) { - comp_err(dev, "waves_effect_check() channels %d not supported", src_fmt->channels); + comp_err(dev, "waves_effect_check() channels %d not supported", + audio_stream_get_channels(src_fmt)); ret = -EINVAL; goto out; } @@ -318,10 +320,10 @@ static int waves_effect_init(struct processing_module *mod) comp_dbg(dev, "waves_effect_init() start"); - sample_format = format_convert_sof_to_me(src_fmt->frame_fmt); + sample_format = format_convert_sof_to_me(audio_stream_get_frm_fmt(src_fmt)); if (sample_format < 0) { comp_err(dev, "waves_effect_init() sof sample format %d not supported", - src_fmt->frame_fmt); + audio_stream_get_frm_fmt(src_fmt)); ret = -EINVAL; goto out; } @@ -346,8 +348,8 @@ static int waves_effect_init(struct processing_module *mod) waves_codec->i_buffer = 0; waves_codec->o_buffer = 0; - waves_codec->i_format.sampleRate = src_fmt->rate; - waves_codec->i_format.numChannels = src_fmt->channels; + waves_codec->i_format.sampleRate = audio_stream_get_rate(src_fmt); + waves_codec->i_format.numChannels = audio_stream_get_channels(src_fmt); waves_codec->i_format.samplesFormat = sample_format; waves_codec->i_format.samplesLayout = buffer_format; waves_codec->o_format = waves_codec->i_format; @@ -356,9 +358,10 @@ static int waves_effect_init(struct processing_module *mod) /* Prepare a buffer for 1 period worth of data * dev->pipeline->period stands for the scheduling period in us */ - waves_codec->buffer_samples = src_fmt->rate * dev->pipeline->period / 1000000; - waves_codec->buffer_bytes = waves_codec->buffer_samples * src_fmt->channels * - waves_codec->sample_size_in_bytes; + waves_codec->buffer_samples = audio_stream_get_rate(src_fmt) * dev->pipeline->period / + 1000000; + waves_codec->buffer_bytes = waves_codec->buffer_samples * + audio_stream_get_channels(src_fmt) * waves_codec->sample_size_in_bytes; // trace allows printing only up-to 4 words at a time // logging all the information in two calls diff --git a/src/audio/module_adapter/module_adapter.c b/src/audio/module_adapter/module_adapter.c index 869221c83460..fc0705ab9861 100644 --- a/src/audio/module_adapter/module_adapter.c +++ b/src/audio/module_adapter/module_adapter.c @@ -89,6 +89,14 @@ struct comp_dev *module_adapter_new(const struct comp_driver *drv, data = spec; break; } + case SOF_COMP_SRC: + { + const struct ipc_config_src *ipc_src = spec; + + size = sizeof(*ipc_src); + data = spec; + break; + } default: { const struct ipc_config_process *ipc_module_adapter = spec; @@ -348,7 +356,7 @@ int module_adapter_prepare(struct comp_dev *dev) if (list_is_empty(&mod->sink_buffer_list)) { for (i = 0; i < mod->num_output_buffers; i++) { struct comp_buffer *buffer = buffer_alloc(buff_size, SOF_MEM_CAPS_RAM, - PLATFORM_DCACHE_ALIGN); + 0, PLATFORM_DCACHE_ALIGN); if (!buffer) { comp_err(dev, "module_adapter_prepare(): failed to allocate local buffer"); ret = -ENOMEM; @@ -368,7 +376,7 @@ int module_adapter_prepare(struct comp_dev *dev) sink_list); buffer_c = buffer_acquire(buffer); - ret = buffer_set_size(buffer_c, buff_size); + ret = buffer_set_size(buffer_c, buff_size, 0); if (ret < 0) { buffer_release(buffer_c); comp_err(dev, "module_adapter_prepare(): buffer_set_size() failed, buff_size = %u", @@ -458,18 +466,20 @@ ca_copy_from_source_to_module(const struct audio_stream __sparse_cache *source, void __sparse_cache *buff, uint32_t buff_size, size_t bytes) { /* head_size - available data until end of source buffer */ - const int without_wrap = audio_stream_bytes_without_wrap(source, source->r_ptr); + const int without_wrap = audio_stream_bytes_without_wrap(source, + audio_stream_get_rptr(source)); uint32_t head_size = MIN(bytes, without_wrap); /* tail_size - residual data to be copied starting from the beginning of the buffer */ uint32_t tail_size = bytes - head_size; /* copy head_size to module buffer */ - memcpy((__sparse_force void *)buff, source->r_ptr, MIN(buff_size, head_size)); + memcpy((__sparse_force void *)buff, audio_stream_get_rptr(source), + MIN(buff_size, head_size)); /* copy residual samples after wrap */ if (tail_size) memcpy((__sparse_force char *)buff + head_size, - audio_stream_wrap(source, (char *)source->r_ptr + head_size), + audio_stream_wrap(source, (char *)audio_stream_get_rptr(source) + head_size), MIN(buff_size, tail_size)); } @@ -484,7 +494,7 @@ ca_copy_from_module_to_sink(const struct audio_stream __sparse_cache *sink, void __sparse_cache *buff, size_t bytes) { /* head_size - free space until end of sink buffer */ - const int without_wrap = audio_stream_bytes_without_wrap(sink, sink->w_ptr); + const int without_wrap = audio_stream_bytes_without_wrap(sink, audio_stream_get_wptr(sink)); uint32_t head_size = MIN(bytes, without_wrap); /* tail_size - rest of the bytes that needs to be written * starting from the beginning of the buffer @@ -492,12 +502,14 @@ ca_copy_from_module_to_sink(const struct audio_stream __sparse_cache *sink, uint32_t tail_size = bytes - head_size; /* copy "head_size" samples to sink buffer */ - memcpy(sink->w_ptr, (__sparse_force void *)buff, MIN(sink->size, head_size)); + memcpy(audio_stream_get_wptr(sink), (__sparse_force void *)buff, + MIN(audio_stream_get_size(sink), head_size)); /* copy rest of the samples after buffer wrap */ if (tail_size) - memcpy(audio_stream_wrap(sink, (char *)sink->w_ptr + head_size), - (__sparse_force char *)buff + head_size, MIN(sink->size, tail_size)); + memcpy(audio_stream_wrap(sink, (char *)audio_stream_get_wptr(sink) + head_size), + (__sparse_force char *)buff + head_size, + MIN(audio_stream_get_size(sink), tail_size)); } /** @@ -513,7 +525,7 @@ static void generate_zeroes(struct comp_buffer __sparse_cache *sink, uint32_t by void *ptr; while (copy_bytes) { - ptr = audio_stream_wrap(&sink->stream, sink->stream.w_ptr); + ptr = audio_stream_wrap(&sink->stream, audio_stream_get_wptr(&sink->stream)); tmp = audio_stream_bytes_without_wrap(&sink->stream, ptr); tmp = MIN(tmp, copy_bytes); ptr = (char *)ptr + tmp; @@ -616,6 +628,8 @@ static void module_adapter_process_output(struct comp_dev *dev) } i++; } + + mod->total_data_produced += mod->output_buffers[0].size; } static uint32_t @@ -751,9 +765,15 @@ static int module_adapter_simple_copy(struct comp_dev *dev) src_c = attr_container_of(mod->input_buffers[i].data, struct comp_buffer __sparse_cache, stream, __sparse_cache); + comp_update_buffer_consume(src_c, mod->input_buffers[i].consumed); } + /* compute data consumed based on pin 0 since it is processed with base config + * which is set for pin 0 + */ + mod->total_data_consumed += mod->input_buffers[0].consumed; + /* release all source buffers */ i = 0; list_for_item(blist, &dev->bsource_list) { @@ -776,6 +796,8 @@ static int module_adapter_simple_copy(struct comp_dev *dev) comp_update_buffer_produce(sink_c, mod->output_buffers[i].size); } + mod->total_data_produced += mod->output_buffers[0].size; + /* release all sink buffers */ i = 0; list_for_item(blist, &dev->bsink_list) { @@ -856,7 +878,6 @@ int module_adapter_copy(struct comp_dev *dev) ca_copy_from_source_to_module(&src_c->stream, mod->input_buffers[i].data, md->mpd.in_buff_size, bytes_to_process); buffer_release(src_c); - i++; } @@ -886,8 +907,12 @@ int module_adapter_copy(struct comp_dev *dev) bzero((__sparse_force void *)mod->input_buffers[i].data, size); mod->input_buffers[i].size = 0; mod->input_buffers[i].consumed = 0; + i++; } + + mod->total_data_consumed += mod->input_buffers[0].consumed; + module_adapter_process_output(dev); return 0; @@ -1125,6 +1150,9 @@ int module_adapter_reset(struct comp_dev *dev) mod->num_input_buffers = 0; mod->num_output_buffers = 0; + mod->total_data_consumed = 0; + mod->total_data_produced = 0; + list_for_item(blist, &mod->sink_buffer_list) { struct comp_buffer *buffer = container_of(blist, struct comp_buffer, sink_list); @@ -1329,6 +1357,17 @@ int module_adapter_unbind(struct comp_dev *dev, void *data) return 0; } + +uint64_t module_adapter_get_total_data_processed(struct comp_dev *dev, + uint32_t stream_no, bool input) +{ + struct processing_module *mod = comp_get_drvdata(dev); + + if (input) + return mod->total_data_produced; + else + return mod->total_data_consumed; +} #else int module_adapter_get_attribute(struct comp_dev *dev, uint32_t type, void *value) { @@ -1355,4 +1394,10 @@ int module_adapter_unbind(struct comp_dev *dev, void *data) { return 0; } + +uint64_t module_adapter_get_total_data_processed(struct comp_dev *dev, + uint32_t stream_no, bool input) +{ + return 0; +} #endif diff --git a/src/audio/multiband_drc/multiband_drc.c b/src/audio/multiband_drc/multiband_drc.c index 29929114795f..a84a55de94b1 100644 --- a/src/audio/multiband_drc/multiband_drc.c +++ b/src/audio/multiband_drc/multiband_drc.c @@ -487,8 +487,8 @@ static int multiband_drc_copy(struct comp_dev *dev) /* Check for changed configuration */ if (comp_is_new_data_blob_available(cd->model_handler)) { cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL); - ret = multiband_drc_setup(cd, (int16_t)source_c->stream.channels, - source_c->stream.rate); + ret = multiband_drc_setup(cd, (int16_t)audio_stream_get_channels(&source_c->stream), + audio_stream_get_rate(&source_c->stream)); if (ret < 0) { comp_err(dev, "multiband_drc_copy(), failed DRC setup"); goto out; @@ -534,14 +534,15 @@ static int multiband_drc_prepare(struct comp_dev *dev) source_c = buffer_acquire(sourceb); /* get source data format */ - cd->source_format = source_c->stream.frame_fmt; + cd->source_format = audio_stream_get_frm_fmt(&source_c->stream); /* Initialize DRC */ comp_dbg(dev, "multiband_drc_prepare(), source_format=%d, sink_format=%d", cd->source_format, cd->source_format); cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL); if (cd->config && cd->process_enabled) { - ret = multiband_drc_setup(cd, source_c->stream.channels, source_c->stream.rate); + ret = multiband_drc_setup(cd, audio_stream_get_channels(&source_c->stream), + audio_stream_get_rate(&source_c->stream)); if (ret < 0) { comp_err(dev, "multiband_drc_prepare() error: multiband_drc_setup failed."); goto out_source; @@ -574,10 +575,10 @@ static int multiband_drc_prepare(struct comp_dev *dev) sink_c = buffer_acquire(sinkb); /* validate sink data format and period bytes */ - if (cd->source_format != sink_c->stream.frame_fmt) { + if (cd->source_format != audio_stream_get_frm_fmt(&sink_c->stream)) { comp_err(dev, "multiband_drc_prepare(): Source fmt %d and sink fmt %d are different.", - cd->source_format, sink_c->stream.frame_fmt); + cd->source_format, audio_stream_get_frm_fmt(&sink_c->stream)); ret = -EINVAL; goto out_sink; } @@ -585,9 +586,9 @@ static int multiband_drc_prepare(struct comp_dev *dev) sink_period_bytes = audio_stream_period_bytes(&sink_c->stream, dev->frames); - if (sink_c->stream.size < sink_period_bytes) { + if (audio_stream_get_size(&sink_c->stream) < sink_period_bytes) { comp_err(dev, "multiband_drc_prepare(), sink buffer size %d is insufficient", - sink_c->stream.size); + audio_stream_get_size(&sink_c->stream)); ret = -ENOMEM; } diff --git a/src/audio/multiband_drc/multiband_drc_generic.c b/src/audio/multiband_drc/multiband_drc_generic.c index 835da243b5cc..ece83afc8458 100644 --- a/src/audio/multiband_drc/multiband_drc_generic.c +++ b/src/audio/multiband_drc/multiband_drc_generic.c @@ -15,7 +15,7 @@ static void multiband_drc_default_pass(const struct comp_dev *dev, struct audio_stream __sparse_cache *sink, uint32_t frames) { - audio_stream_copy(source, 0, sink, 0, source->channels * frames); + audio_stream_copy(source, 0, sink, 0, audio_stream_get_channels(source) * frames); } static void multiband_drc_process_emp_crossover(struct multiband_drc_state *state, @@ -215,14 +215,14 @@ static void multiband_drc_s16_default(const struct comp_dev *dev, int32_t buf_drc_sink[PLATFORM_MAX_CHANNELS * SOF_MULTIBAND_DRC_MAX_BANDS]; int32_t *band_buf_drc_src; int32_t *band_buf_drc_sink; - int16_t *x = source->r_ptr; - int16_t *y = sink->w_ptr; + int16_t *x = audio_stream_get_rptr(source); + int16_t *y = audio_stream_get_wptr(sink); int band; int nbuf; int npcm; int ch; int i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int nband = cd->config->num_bands; int enable_emp_deemp = cd->config->enable_emp_deemp; int samples = frames * nch; @@ -282,14 +282,14 @@ static void multiband_drc_s24_default(const struct comp_dev *dev, int32_t buf_drc_sink[PLATFORM_MAX_CHANNELS * SOF_MULTIBAND_DRC_MAX_BANDS]; int32_t *band_buf_drc_src; int32_t *band_buf_drc_sink; - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); int band; int nbuf; int npcm; int ch; int i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int nband = cd->config->num_bands; int enable_emp_deemp = cd->config->enable_emp_deemp; int samples = frames * nch; @@ -349,14 +349,14 @@ static void multiband_drc_s32_default(const struct comp_dev *dev, int32_t buf_drc_sink[PLATFORM_MAX_CHANNELS * SOF_MULTIBAND_DRC_MAX_BANDS]; int32_t *band_buf_drc_src; int32_t *band_buf_drc_sink; - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); int band; int nbuf; int npcm; int ch; int i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); int nband = cd->config->num_bands; int enable_emp_deemp = cd->config->enable_emp_deemp; int samples = frames * nch; diff --git a/src/audio/mux/mux.c b/src/audio/mux/mux.c index af6f9976f284..3ebbf838ea72 100644 --- a/src/audio/mux/mux.c +++ b/src/audio/mux/mux.c @@ -263,6 +263,7 @@ static void set_mux_params(struct processing_module *mod) struct comp_dev *dev = mod->dev; struct comp_buffer *sink, *source; struct comp_buffer __sparse_cache *sink_c, *source_c; + enum sof_ipc_frame frame_fmt, valid_fmt; struct list_item *source_list; int i, j, valid_bit_depth; const uint32_t byte_align = 1; @@ -294,16 +295,18 @@ static void set_mux_params(struct processing_module *mod) struct ipc4_audio_format out_fmt; out_fmt = cd->md.output_format; - sink_c->stream.channels = out_fmt.channels_count; - sink_c->stream.rate = out_fmt.sampling_frequency; audio_stream_fmt_conversion(out_fmt.depth, out_fmt.valid_bit_depth, - &sink_c->stream.frame_fmt, - &sink_c->stream.valid_sample_fmt, + &frame_fmt, &valid_fmt, out_fmt.s_type); + audio_stream_set_frm_fmt(&sink_c->stream, frame_fmt); + audio_stream_set_valid_fmt(&sink_c->stream, valid_fmt); + audio_stream_set_channels(&sink_c->stream, out_fmt.channels_count); + audio_stream_set_rate(&sink_c->stream, out_fmt.sampling_frequency); + sink_c->buffer_fmt = out_fmt.interleaving_style; - params->frame_fmt = sink_c->stream.frame_fmt; + params->frame_fmt = audio_stream_get_frm_fmt(&sink_c->stream); for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) sink_c->chmap[i] = (out_fmt.ch_map >> i * 4) & 0xf; @@ -325,14 +328,13 @@ static void set_mux_params(struct processing_module *mod) cd->config.streams[j].pipeline_id = source_c->pipeline_id; valid_bit_depth = cd->md.base_cfg.audio_fmt.valid_bit_depth; if (j == BASE_CFG_QUEUED_ID) { - source_c->stream.channels = - cd->md.base_cfg.audio_fmt.channels_count; - source_c->stream.rate = - cd->md.base_cfg.audio_fmt.sampling_frequency; + audio_stream_set_channels(&source_c->stream, + cd->md.base_cfg.audio_fmt.channels_count); + audio_stream_set_rate(&source_c->stream, + cd->md.base_cfg.audio_fmt.sampling_frequency); audio_stream_fmt_conversion(cd->md.base_cfg.audio_fmt.depth, valid_bit_depth, - &source_c->stream.frame_fmt, - &source_c->stream.valid_sample_fmt, + &frame_fmt, &valid_fmt, cd->md.base_cfg.audio_fmt.s_type); source_c->buffer_fmt = cd->md.base_cfg.audio_fmt.interleaving_style; @@ -342,20 +344,25 @@ static void set_mux_params(struct processing_module *mod) (cd->md.base_cfg.audio_fmt.ch_map >> i * 4) & 0xf; } else { /* set parameters for reference input channels */ - source_c->stream.channels = - cd->md.reference_format.channels_count; - source_c->stream.rate = cd->md.reference_format.sampling_frequency; + audio_stream_set_channels(&source_c->stream, + cd->md.reference_format.channels_count); + audio_stream_set_rate(&source_c->stream, + cd->md.reference_format.sampling_frequency); audio_stream_fmt_conversion(cd->md.reference_format.depth, cd->md.reference_format.valid_bit_depth, - &source_c->stream.frame_fmt, - &source_c->stream.valid_sample_fmt, + &frame_fmt, &valid_fmt, cd->md.reference_format.s_type); + source_c->buffer_fmt = cd->md.reference_format.interleaving_style; for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) source_c->chmap[i] = (cd->md.reference_format.ch_map >> i * 4) & 0xf; } + + audio_stream_set_frm_fmt(&source_c->stream, frame_fmt); + audio_stream_set_valid_fmt(&source_c->stream, valid_fmt); + source_c->hw_params_configured = true; buffer_release(source_c); } @@ -418,8 +425,8 @@ static void mux_prepare_active_look_up(struct comp_data *cd, if (!source) continue; - if (cd->lookup[0].copy_elem[elem].in_ch >= source->channels || - cd->lookup[0].copy_elem[elem].out_ch >= sink->channels) + if (cd->lookup[0].copy_elem[elem].in_ch >= audio_stream_get_channels(source) || + cd->lookup[0].copy_elem[elem].out_ch >= audio_stream_get_channels(sink)) continue; cd->active_lookup.copy_elem[active_elem] = cd->lookup[0].copy_elem[elem]; @@ -439,8 +446,8 @@ static void demux_prepare_active_look_up(struct comp_data *cd, /* init pointers */ for (elem = 0; elem < look_up->num_elems; elem++) { - if (look_up->copy_elem[elem].in_ch >= source->channels || - look_up->copy_elem[elem].out_ch >= sink->channels) + if (look_up->copy_elem[elem].in_ch >= audio_stream_get_channels(source) || + look_up->copy_elem[elem].out_ch >= audio_stream_get_channels(sink)) continue; cd->active_lookup.copy_elem[active_elem] = look_up->copy_elem[elem]; diff --git a/src/audio/mux/mux_generic.c b/src/audio/mux/mux_generic.c index 7f5ba0f1a8ca..dd58cedbbd6b 100644 --- a/src/audio/mux/mux_generic.c +++ b/src/audio/mux/mux_generic.c @@ -122,13 +122,13 @@ static void mux_init_look_up_pointers_s16(struct audio_stream __sparse_cache *si for (elem = 0; elem < lookup->num_elems; elem++) { source = sources[lookup->copy_elem[elem].stream_id]; - lookup->copy_elem[elem].src = (int16_t *)source->r_ptr + + lookup->copy_elem[elem].src = (int16_t *)audio_stream_get_rptr(source) + lookup->copy_elem[elem].in_ch; - lookup->copy_elem[elem].src_inc = source->channels; + lookup->copy_elem[elem].src_inc = audio_stream_get_channels(source); - lookup->copy_elem[elem].dest = (int16_t *)sink->w_ptr + + lookup->copy_elem[elem].dest = (int16_t *)audio_stream_get_wptr(sink) + lookup->copy_elem[elem].out_ch; - lookup->copy_elem[elem].dest_inc = sink->channels; + lookup->copy_elem[elem].dest_inc = audio_stream_get_channels(sink); } } @@ -140,13 +140,13 @@ static void demux_init_look_up_pointers_s16(struct audio_stream __sparse_cache * /* init pointers */ for (elem = 0; elem < lookup->num_elems; elem++) { - lookup->copy_elem[elem].src = (int16_t *)source->r_ptr + + lookup->copy_elem[elem].src = (int16_t *)audio_stream_get_rptr(source) + lookup->copy_elem[elem].in_ch; - lookup->copy_elem[elem].src_inc = source->channels; + lookup->copy_elem[elem].src_inc = audio_stream_get_channels(source); - lookup->copy_elem[elem].dest = (int16_t *)sink->w_ptr + + lookup->copy_elem[elem].dest = (int16_t *)audio_stream_get_wptr(sink) + lookup->copy_elem[elem].out_ch; - lookup->copy_elem[elem].dest_inc = sink->channels; + lookup->copy_elem[elem].dest_inc = audio_stream_get_channels(sink); } } @@ -324,13 +324,13 @@ static void mux_init_look_up_pointers_s32(struct audio_stream __sparse_cache *si for (elem = 0; elem < lookup->num_elems; elem++) { source = sources[lookup->copy_elem[elem].stream_id]; - lookup->copy_elem[elem].src = (int32_t *)source->r_ptr + + lookup->copy_elem[elem].src = (int32_t *)audio_stream_get_rptr(source) + lookup->copy_elem[elem].in_ch; - lookup->copy_elem[elem].src_inc = source->channels; + lookup->copy_elem[elem].src_inc = audio_stream_get_channels(source); - lookup->copy_elem[elem].dest = (int32_t *)sink->w_ptr + + lookup->copy_elem[elem].dest = (int32_t *)audio_stream_get_wptr(sink) + lookup->copy_elem[elem].out_ch; - lookup->copy_elem[elem].dest_inc = sink->channels; + lookup->copy_elem[elem].dest_inc = audio_stream_get_channels(sink); } } @@ -342,13 +342,13 @@ static void demux_init_look_up_pointers_s32(struct audio_stream __sparse_cache * /* init pointers */ for (elem = 0; elem < lookup->num_elems; elem++) { - lookup->copy_elem[elem].src = (int32_t *)source->r_ptr + + lookup->copy_elem[elem].src = (int32_t *)audio_stream_get_rptr(source) + lookup->copy_elem[elem].in_ch; - lookup->copy_elem[elem].src_inc = source->channels; + lookup->copy_elem[elem].src_inc = audio_stream_get_channels(source); - lookup->copy_elem[elem].dest = (int32_t *)sink->w_ptr + + lookup->copy_elem[elem].dest = (int32_t *)audio_stream_get_wptr(sink) + lookup->copy_elem[elem].out_ch; - lookup->copy_elem[elem].dest_inc = sink->channels; + lookup->copy_elem[elem].dest_inc = audio_stream_get_channels(sink); } } @@ -535,7 +535,7 @@ mux_func mux_get_processing_function(struct processing_module *mod) for (i = 0; i < ARRAY_SIZE(mux_func_map); i++) { struct comp_buffer __sparse_cache *sink_c = buffer_acquire(sinkb); - enum sof_ipc_frame fmt = sink_c->stream.frame_fmt; + enum sof_ipc_frame fmt = audio_stream_get_frm_fmt(&sink_c->stream); if (fmt == mux_func_map[i].frame_format) @@ -559,7 +559,7 @@ demux_func demux_get_processing_function(struct processing_module *mod) for (i = 0; i < ARRAY_SIZE(mux_func_map); i++) { struct comp_buffer __sparse_cache *source_c = buffer_acquire(sourceb); - enum sof_ipc_frame fmt = source_c->stream.frame_fmt; + enum sof_ipc_frame fmt = audio_stream_get_frm_fmt(&source_c->stream); buffer_release(source_c); diff --git a/src/audio/pcm_converter/pcm_converter.c b/src/audio/pcm_converter/pcm_converter.c index f918c45f9f24..6c3753b8d8e7 100644 --- a/src/audio/pcm_converter/pcm_converter.c +++ b/src/audio/pcm_converter/pcm_converter.c @@ -23,9 +23,9 @@ int pcm_convert_as_linear(const struct audio_stream __sparse_cache *source, uint const int s_size_out = audio_stream_sample_bytes(sink); const int log2_s_size_in = ffs(s_size_in) - 1; const int log2_s_size_out = ffs(s_size_out) - 1; - char *r_ptr = audio_stream_get_frag(source, source->r_ptr, ioffset, + char *r_ptr = audio_stream_get_frag(source, audio_stream_get_rptr(source), ioffset, s_size_in); - char *w_ptr = audio_stream_get_frag(sink, sink->w_ptr, ooffset, + char *w_ptr = audio_stream_get_frag(sink, audio_stream_get_wptr(sink), ooffset, s_size_out); int i = 0; int chunk; diff --git a/src/audio/pcm_converter/pcm_converter_generic.c b/src/audio/pcm_converter/pcm_converter_generic.c index 1cc7dc38685d..0ed6555b4780 100644 --- a/src/audio/pcm_converter/pcm_converter_generic.c +++ b/src/audio/pcm_converter/pcm_converter_generic.c @@ -35,8 +35,8 @@ static int pcm_convert_s16_to_s24(const struct audio_stream __sparse_cache *sour uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int16_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int16_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -64,8 +64,8 @@ static int pcm_convert_s24_to_s16(const struct audio_stream __sparse_cache *sour uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int16_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int16_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -97,8 +97,8 @@ static int pcm_convert_s16_to_s32(const struct audio_stream __sparse_cache *sour uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int16_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int16_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -126,8 +126,8 @@ static int pcm_convert_s32_to_s16(const struct audio_stream __sparse_cache *sour uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int16_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int16_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -159,8 +159,8 @@ static int pcm_convert_s24_to_s32(const struct audio_stream __sparse_cache *sour uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -188,8 +188,8 @@ static int pcm_convert_s32_to_s24(const struct audio_stream __sparse_cache *sour uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -217,8 +217,8 @@ static int pcm_convert_s32_to_s24_be(const struct audio_stream __sparse_cache *s uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -532,8 +532,8 @@ static int pcm_convert_s16_c16_to_s16_c32(const struct audio_stream __sparse_cac uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int16_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int16_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -561,8 +561,8 @@ static int pcm_convert_s16_c32_to_s16_c16(const struct audio_stream __sparse_cac uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int16_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int16_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -591,8 +591,8 @@ static int pcm_convert_s16_c32_to_s32_c32(const struct audio_stream __sparse_cac uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -620,8 +620,8 @@ static int pcm_convert_s32_c32_to_s16_c32(const struct audio_stream __sparse_cac uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -650,8 +650,8 @@ static int pcm_convert_s16_c32_to_s24_c32(const struct audio_stream __sparse_cac uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -679,8 +679,8 @@ static int pcm_convert_s24_c32_to_s16_c32(const struct audio_stream __sparse_cac uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -710,8 +710,8 @@ static int pcm_convert_s24_c24_to_s24_c32(const struct audio_stream __sparse_cac uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - uint8_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + uint8_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -740,8 +740,8 @@ static int pcm_convert_s24_c32_to_s24_c24(const struct audio_stream __sparse_cac uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - uint8_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + uint8_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i, n; @@ -774,8 +774,8 @@ static int pcm_convert_s24_c32_to_s24_c24_link_gtw(const struct audio_stream __s uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - uint16_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + uint16_t *dst = audio_stream_get_wptr(sink); int processed; int nmax, i = 0, n = 0; @@ -843,35 +843,56 @@ const struct pcm_func_vc_map pcm_func_vc_map[] = { #endif #if CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S24LE { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, - ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh | ipc4_gtw_host), ipc4_bidirection, - audio_stream_copy}, + ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh | ipc4_gtw_host | ipc4_gtw_dmic), + ipc4_bidirection, audio_stream_copy}, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_link | ipc4_gtw_alh, ipc4_playback, pcm_convert_s24_to_s32 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, - ipc4_gtw_link | ipc4_gtw_alh, ipc4_capture, pcm_convert_s32_to_s24 }, + ipc4_gtw_link | ipc4_gtw_alh | ipc4_gtw_dmic, ipc4_capture, + pcm_convert_s32_to_s24 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_host, ipc4_playback, pcm_convert_s32_to_s24 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_host, ipc4_capture, pcm_convert_s24_to_s32 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, - ipc4_gtw_all, ipc4_bidirection, pcm_convert_s24_to_s32}, + ipc4_gtw_all & ~ipc4_gtw_host, ipc4_bidirection, pcm_convert_s24_to_s32}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, + ipc4_gtw_host, ipc4_playback, audio_stream_copy}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, + ipc4_gtw_host, ipc4_capture, pcm_convert_s24_to_s32}, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, - ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh), ipc4_bidirection, + ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh | ipc4_gtw_host), ipc4_bidirection, pcm_convert_s32_to_s24 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_link | ipc4_gtw_alh, ipc4_playback, pcm_convert_s32_to_s24_be }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_link | ipc4_gtw_alh, ipc4_capture, pcm_convert_s32_to_s24 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, + ipc4_gtw_host, ipc4_playback, pcm_convert_s32_to_s24 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, + ipc4_gtw_host, ipc4_capture, pcm_convert_s32_to_s24_be }, #endif #if CONFIG_PCM_CONVERTER_FORMAT_S24LE && CONFIG_PCM_CONVERTER_FORMAT_S16LE { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, - SOF_IPC_FRAME_S24_4LE, ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh), + SOF_IPC_FRAME_S24_4LE, + ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh | ipc4_gtw_host), ipc4_bidirection, pcm_convert_s16_to_s24 }, { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_link | ipc4_gtw_alh, ipc4_playback, pcm_convert_s16_to_s32}, + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE, ipc4_gtw_host, + ipc4_playback, pcm_convert_s16_to_s24 }, + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE, ipc4_gtw_host, + ipc4_capture, pcm_convert_s16_to_s32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, + SOF_IPC_FRAME_S16_LE, ipc4_gtw_all & ~ipc4_gtw_host, + ipc4_bidirection, pcm_convert_s24_to_s16 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, + SOF_IPC_FRAME_S16_LE, ipc4_gtw_host, ipc4_playback, pcm_convert_s32_to_s16 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, - SOF_IPC_FRAME_S16_LE, ipc4_gtw_all, ipc4_bidirection, pcm_convert_s24_to_s16 }, + SOF_IPC_FRAME_S16_LE, ipc4_gtw_host, ipc4_capture, pcm_convert_s24_to_s16 }, #endif #if CONFIG_PCM_CONVERTER_FORMAT_S24_C24_AND_S24_C32 { SOF_IPC_FRAME_S24_3LE, SOF_IPC_FRAME_S24_3LE, SOF_IPC_FRAME_S32_LE, diff --git a/src/audio/pcm_converter/pcm_converter_hifi3.c b/src/audio/pcm_converter/pcm_converter_hifi3.c index b727fdae209b..0980cc656a93 100644 --- a/src/audio/pcm_converter/pcm_converter_hifi3.c +++ b/src/audio/pcm_converter/pcm_converter_hifi3.c @@ -44,8 +44,8 @@ static int pcm_convert_s16_to_s24(const struct audio_stream __sparse_cache *sour uint32_t nmax, i, n, m, left, left_samples; ae_valign inu = AE_ZALIGN64(); ae_valign outu = AE_ZALIGN64(); - int16_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int16_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int16x4 *in = audio_stream_wrap(source, src + ioffset); ae_int32x2 *out = audio_stream_wrap(sink, dst + ooffset); @@ -120,8 +120,8 @@ static int pcm_convert_s24_to_s16(const struct audio_stream __sparse_cache *sour uint32_t nmax, i, n, m, left, left_samples; ae_valign inu = AE_ZALIGN64(); ae_valign outu = AE_ZALIGN64(); - ae_int32 *src = source->r_ptr; - ae_int16 *dst = sink->w_ptr; + ae_int32 *src = audio_stream_get_rptr(source); + ae_int16 *dst = audio_stream_get_wptr(sink); ae_int32x2 *in = audio_stream_wrap(source, src + ioffset); ae_int16x4 *out = audio_stream_wrap(sink, dst + ooffset); @@ -185,8 +185,8 @@ static int pcm_convert_s16_to_s32(const struct audio_stream __sparse_cache *sour uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int16_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int16_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int16x4 sample = AE_ZERO16(); uint32_t nmax, i, n, m, left, left_samples; ae_valign inu = AE_ZALIGN64(); @@ -241,8 +241,8 @@ static int pcm_convert_s32_to_s16(const struct audio_stream __sparse_cache *sour uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int16_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int16_t *dst = audio_stream_get_wptr(sink); ae_int16x4 sample = AE_ZERO16(); ae_int32x2 sample_1 = AE_ZERO32(); ae_int32x2 sample_2 = AE_ZERO32(); @@ -307,8 +307,8 @@ static int pcm_convert_s24_to_s32(const struct audio_stream __sparse_cache *sour uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int32x2 sample = AE_ZERO32(); uint32_t nmax, i, n, m, left_samples; ae_valign outu = AE_ZALIGN64(); @@ -372,8 +372,8 @@ static int pcm_convert_s32_to_s24(const struct audio_stream __sparse_cache *sour uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int32x2 sample = AE_ZERO32(); uint32_t nmax, i, n, m, left_samples; ae_valign outu = AE_ZALIGN64(); @@ -417,8 +417,8 @@ static int pcm_convert_s32_to_s24_be(const struct audio_stream __sparse_cache *s uint32_t ioffset, struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int32x2 sample = AE_ZERO32(); uint32_t nmax, i, n, m, left_samples; ae_valign outu = AE_ZALIGN64(); @@ -815,8 +815,8 @@ static int pcm_convert_s16_c16_to_s16_c32(const struct audio_stream __sparse_cac struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int16_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int16_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int16x4 sample = AE_ZERO16(); uint32_t nmax, i, n, m, left, left_samples; ae_valign inu = AE_ZALIGN64(); @@ -865,8 +865,8 @@ static int pcm_convert_s16_c32_to_s16_c16(const struct audio_stream __sparse_cac struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int16_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int16_t *dst = audio_stream_get_wptr(sink); ae_int16x4 sample = AE_ZERO16(); ae_int32x2 sample_1 = AE_ZERO32(); ae_int32x2 sample_2 = AE_ZERO32(); @@ -924,8 +924,8 @@ static int pcm_convert_s16_c32_to_s32_c32(const struct audio_stream __sparse_cac struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int32x2 sample = AE_ZERO32(); uint32_t nmax, i, n, m, left_samples; ae_valign outu = AE_ZALIGN64(); @@ -967,8 +967,8 @@ static int pcm_convert_s32_c32_to_s16_c32(const struct audio_stream __sparse_cac struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int32x2 sample = AE_ZERO32(); uint32_t nmax, i, n, m, left_samples; ae_valign outu = AE_ZALIGN64(); @@ -1012,8 +1012,8 @@ static int pcm_convert_s16_c32_to_s24_c32(const struct audio_stream __sparse_cac struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int32x2 sample = AE_ZERO32(); uint32_t nmax, i, n, m, left_samples; ae_valign outu = AE_ZALIGN64(); @@ -1067,8 +1067,8 @@ static int pcm_convert_s24_c32_to_s16_c32(const struct audio_stream __sparse_cac struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int32x2 sample = AE_ZERO32(); uint32_t nmax, i, n, m, left_samples; ae_valign outu = AE_ZALIGN64(); @@ -1114,8 +1114,8 @@ static int pcm_convert_s24_c24_to_s24_c32(const struct audio_stream __sparse_cac struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - uint8_t *src = source->r_ptr; - int32_t *dst = sink->w_ptr; + uint8_t *src = audio_stream_get_rptr(source); + int32_t *dst = audio_stream_get_wptr(sink); ae_int24x2 sample24 = AE_ZERO24(); ae_int32x2 sample = AE_ZERO32(); uint32_t nmax, i, n, m, left_samples; @@ -1161,8 +1161,8 @@ static int pcm_convert_s24_c32_to_s24_c24(const struct audio_stream __sparse_cac struct audio_stream __sparse_cache *sink, uint32_t ooffset, uint32_t samples) { - int32_t *src = source->r_ptr; - uint8_t *dst = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + uint8_t *dst = audio_stream_get_wptr(sink); ae_int32x2 sample = AE_ZERO32(); ae_int24x2 sample24 = AE_ZERO24(); uint32_t nmax, i, n, m, left_samples; @@ -1237,35 +1237,56 @@ const struct pcm_func_vc_map pcm_func_vc_map[] = { #endif #if CONFIG_PCM_CONVERTER_FORMAT_S32LE && CONFIG_PCM_CONVERTER_FORMAT_S24LE { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, - ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh | ipc4_gtw_host), ipc4_bidirection, - audio_stream_copy}, + ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh | ipc4_gtw_host | ipc4_gtw_dmic), + ipc4_bidirection, audio_stream_copy}, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_link | ipc4_gtw_alh, ipc4_playback, pcm_convert_s24_to_s32 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, - ipc4_gtw_link | ipc4_gtw_alh, ipc4_capture, pcm_convert_s32_to_s24 }, + ipc4_gtw_link | ipc4_gtw_alh | ipc4_gtw_dmic, ipc4_capture, + pcm_convert_s32_to_s24 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_host, ipc4_playback, pcm_convert_s32_to_s24 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_host, ipc4_capture, pcm_convert_s24_to_s32 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, - ipc4_gtw_all, ipc4_bidirection, pcm_convert_s24_to_s32}, + ipc4_gtw_all & ~ipc4_gtw_host, ipc4_bidirection, pcm_convert_s24_to_s32}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, + ipc4_gtw_host, ipc4_playback, audio_stream_copy}, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, + ipc4_gtw_host, ipc4_capture, pcm_convert_s24_to_s32}, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, - ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh), ipc4_bidirection, + ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh | ipc4_gtw_host), ipc4_bidirection, pcm_convert_s32_to_s24 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_link | ipc4_gtw_alh, ipc4_playback, pcm_convert_s32_to_s24_be }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_link | ipc4_gtw_alh, ipc4_capture, pcm_convert_s32_to_s24 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, + ipc4_gtw_host, ipc4_playback, pcm_convert_s32_to_s24 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, + ipc4_gtw_host, ipc4_capture, pcm_convert_s32_to_s24_be }, #endif #if CONFIG_PCM_CONVERTER_FORMAT_S24LE && CONFIG_PCM_CONVERTER_FORMAT_S16LE { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, - SOF_IPC_FRAME_S24_4LE, ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh), + SOF_IPC_FRAME_S24_4LE, + ipc4_gtw_all & ~(ipc4_gtw_link | ipc4_gtw_alh | ipc4_gtw_host), ipc4_bidirection, pcm_convert_s16_to_s24 }, { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, ipc4_gtw_link | ipc4_gtw_alh, ipc4_playback, pcm_convert_s16_to_s32}, + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE, ipc4_gtw_host, + ipc4_playback, pcm_convert_s16_to_s24 }, + { SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S16_LE, SOF_IPC_FRAME_S32_LE, + SOF_IPC_FRAME_S24_4LE, ipc4_gtw_host, + ipc4_capture, pcm_convert_s16_to_s32 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, + SOF_IPC_FRAME_S16_LE, ipc4_gtw_all & ~ipc4_gtw_host, + ipc4_bidirection, pcm_convert_s24_to_s16 }, + { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, + SOF_IPC_FRAME_S16_LE, ipc4_gtw_host, ipc4_playback, pcm_convert_s32_to_s16 }, { SOF_IPC_FRAME_S32_LE, SOF_IPC_FRAME_S24_4LE, SOF_IPC_FRAME_S16_LE, - SOF_IPC_FRAME_S16_LE, ipc4_gtw_all, ipc4_bidirection, pcm_convert_s24_to_s16 }, + SOF_IPC_FRAME_S16_LE, ipc4_gtw_host, ipc4_capture, pcm_convert_s24_to_s16 }, #endif #if CONFIG_PCM_CONVERTER_FORMAT_S24_C24_AND_S24_C32 { SOF_IPC_FRAME_S24_3LE, SOF_IPC_FRAME_S24_3LE, SOF_IPC_FRAME_S32_LE, diff --git a/src/audio/pipeline/pipeline-graph.c b/src/audio/pipeline/pipeline-graph.c index 809ab7c49d40..a4360c1de618 100644 --- a/src/audio/pipeline/pipeline-graph.c +++ b/src/audio/pipeline/pipeline-graph.c @@ -359,6 +359,17 @@ static int pipeline_comp_reset(struct comp_dev *current, } } + /* two cases for a component still being active here: + * 1. trigger function failed to handle stop event + * 2. trigger functon skipped due to error of other component's trigger function + */ + if (current->state == COMP_STATE_ACTIVE) { + pipe_warn(current->pipeline, "pipeline_comp_reset(): component is in active state, try to stop it"); + err = comp_trigger(current, COMP_TRIGGER_STOP); + if (err) + pipe_err(current->pipeline, "pipeline_comp_reset(): failed to recover"); + } + err = comp_reset(current); if (err < 0 || err == PPL_STATUS_PATH_STOP) return err; diff --git a/src/audio/pipeline/pipeline-params.c b/src/audio/pipeline/pipeline-params.c index ecdac1249c78..253f958f3f67 100644 --- a/src/audio/pipeline/pipeline-params.c +++ b/src/audio/pipeline/pipeline-params.c @@ -138,9 +138,9 @@ static void pipeline_update_buffer_pcm_params(struct comp_buffer __sparse_cache int i; params->buffer_fmt = buffer->buffer_fmt; - params->frame_fmt = buffer->stream.frame_fmt; - params->rate = buffer->stream.rate; - params->channels = buffer->stream.channels; + params->frame_fmt = audio_stream_get_frm_fmt(&buffer->stream); + params->rate = audio_stream_get_rate(&buffer->stream); + params->channels = audio_stream_get_channels(&buffer->stream); for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) params->chmap[i] = buffer->chmap[i]; } diff --git a/src/audio/pipeline/pipeline-stream.c b/src/audio/pipeline/pipeline-stream.c index ab60c11b3c16..3bb7bab2dc3a 100644 --- a/src/audio/pipeline/pipeline-stream.c +++ b/src/audio/pipeline/pipeline-stream.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -325,16 +326,17 @@ static int pipeline_comp_trigger(struct comp_dev *current, * Initialization delay is only used with SSP, where we * don't use more than one DAI per copier */ - struct comp_dev *dai = comp_get_dai(current, 0); - - if (dai) { - struct dai_data *dd = comp_get_drvdata(dai); - - ppl_data->delay_ms = dai_get_init_delay_ms(dd->dai); - } else { - /* Chain DMA case */ - ppl_data->delay_ms = 0; - } + struct dai_data *dd; +#if CONFIG_IPC_MAJOR_3 + dd = comp_get_drvdata(current); +#elif CONFIG_IPC_MAJOR_4 + struct copier_data *cd = comp_get_drvdata(current); + + dd = cd->dd[0]; +#else +#error Unknown IPC major version +#endif + ppl_data->delay_ms = dai_get_init_delay_ms(dd->dai); } break; default: diff --git a/src/audio/rtnr/rtnr.c b/src/audio/rtnr/rtnr.c index 6d86a775962c..890756ecc660 100644 --- a/src/audio/rtnr/rtnr.c +++ b/src/audio/rtnr/rtnr.c @@ -345,11 +345,12 @@ static int rtnr_params(struct comp_dev *dev, struct sof_ipc_stream_params *param sink_c = buffer_acquire(sinkb); /* set source/sink_frames/rate */ - cd->source_rate = source_c->stream.rate; - cd->sink_rate = sink_c->stream.rate; - cd->sources_stream[0].rate = source_c->stream.rate; - cd->sink_stream.rate = sink_c->stream.rate; - channels_valid = source_c->stream.channels == sink_c->stream.channels; + cd->source_rate = audio_stream_get_rate(&source_c->stream); + cd->sink_rate = audio_stream_get_rate(&sink_c->stream); + cd->sources_stream[0].rate = audio_stream_get_rate(&source_c->stream); + cd->sink_stream.rate = audio_stream_get_rate(&sink_c->stream); + channels_valid = audio_stream_get_channels(&source_c->stream) == + audio_stream_get_channels(&sink_c->stream); if (!cd->sink_rate) { comp_err(dev, "rtnr_nr_params(), zero sink rate"); @@ -379,14 +380,14 @@ static int rtnr_params(struct comp_dev *dev, struct sof_ipc_stream_params *param } /* set source/sink stream channels */ - cd->sources_stream[0].channels = source_c->stream.channels; - cd->sink_stream.channels = sink_c->stream.channels; + cd->sources_stream[0].channels = audio_stream_get_channels(&source_c->stream); + cd->sink_stream.channels = audio_stream_get_channels(&sink_c->stream); /* set source/sink stream overrun/underrun permitted */ - cd->sources_stream[0].overrun_permitted = source_c->stream.overrun_permitted; - cd->sink_stream.overrun_permitted = sink_c->stream.overrun_permitted; - cd->sources_stream[0].underrun_permitted = source_c->stream.underrun_permitted; - cd->sink_stream.underrun_permitted = sink_c->stream.underrun_permitted; + cd->sources_stream[0].overrun_permitted = audio_stream_get_overrun(&source_c->stream); + cd->sink_stream.overrun_permitted = audio_stream_get_overrun(&sink_c->stream); + cd->sources_stream[0].underrun_permitted = audio_stream_get_underrun(&source_c->stream); + cd->sink_stream.underrun_permitted = audio_stream_get_underrun(&sink_c->stream); out: buffer_release(sink_c); @@ -729,25 +730,25 @@ static void rtnr_copy_from_sof_stream(struct audio_stream_rtnr *dst, struct audio_stream __sparse_cache *src) { - dst->size = src->size; - dst->avail = src->avail; - dst->free = src->free; - dst->w_ptr = src->w_ptr; - dst->r_ptr = src->r_ptr; - dst->addr = src->addr; - dst->end_addr = src->end_addr; + dst->size = audio_stream_get_size(src); + dst->avail = audio_stream_get_avail(src); + dst->free = audio_stream_get_free(src); + dst->w_ptr = audio_stream_get_wptr(src); + dst->r_ptr = audio_stream_get_rptr(src); + dst->addr = audio_stream_get_addr(src); + dst->end_addr = audio_stream_get_end_addr(src); } static void rtnr_copy_to_sof_stream(struct audio_stream __sparse_cache *dst, struct audio_stream_rtnr *src) { - dst->size = src->size; - dst->avail = src->avail; - dst->free = src->free; - dst->w_ptr = src->w_ptr; - dst->r_ptr = src->r_ptr; - dst->addr = src->addr; - dst->end_addr = src->end_addr; + audio_stream_set_size(dst, src->size); + audio_stream_set_avail(dst, src->avail); + audio_stream_set_free(dst, src->free); + audio_stream_set_wptr(dst, src->w_ptr); + audio_stream_set_rptr(dst, src->r_ptr); + audio_stream_set_addr(dst, src->addr); + audio_stream_set_end_addr(dst, src->end_addr); } /* copy and process stream data from source to sink buffers */ @@ -779,7 +780,8 @@ static int rtnr_copy(struct comp_dev *dev) source = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); /* put empty data into output queue*/ - RTKMA_API_First_Copy(cd->rtk_agl, cd->source_rate, source->stream.channels); + RTKMA_API_First_Copy(cd->rtk_agl, cd->source_rate, + audio_stream_get_channels(&source->stream)); sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); @@ -835,7 +837,7 @@ static int rtnr_copy(struct comp_dev *dev) buffer_stream_invalidate(source, cl.source_bytes); audio_stream_copy(&source->stream, 0, &sink->stream, 0, - source->stream.channels * cl.frames); + audio_stream_get_channels(&source->stream) * cl.frames); buffer_stream_writeback(sink, cl.sink_bytes); comp_update_buffer_consume(source, cl.source_bytes); @@ -873,8 +875,8 @@ static int rtnr_prepare(struct comp_dev *dev) /* Get sink data format */ sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); sink_c = buffer_acquire(sinkb); - cd->sink_format = sink_c->stream.frame_fmt; - cd->sink_stream.frame_fmt = sink_c->stream.frame_fmt; + cd->sink_format = audio_stream_get_frm_fmt(&sink_c->stream); + cd->sink_stream.frame_fmt = audio_stream_get_frm_fmt(&sink_c->stream); buffer_release(sink_c); /* Check source and sink PCM format and get processing function */ diff --git a/src/audio/selector/selector.c b/src/audio/selector/selector.c index f530435c768f..b2c5d1c92f1b 100644 --- a/src/audio/selector/selector.c +++ b/src/audio/selector/selector.c @@ -94,7 +94,7 @@ static int selector_verify_params(struct comp_dev *dev, * pipeline_comp_hw_params() */ out_channels = cd->config.out_channels_count ? - cd->config.out_channels_count : buffer_c->stream.channels; + cd->config.out_channels_count : audio_stream_get_channels(&buffer_c->stream); params->channels = out_channels; } else { /* fetch source buffer for capture */ @@ -115,7 +115,7 @@ static int selector_verify_params(struct comp_dev *dev, * pipeline_comp_hw_params() */ in_channels = cd->config.in_channels_count ? - cd->config.in_channels_count : buffer_c->stream.channels; + cd->config.in_channels_count : audio_stream_get_channels(&buffer_c->stream); params->channels = in_channels; } @@ -126,7 +126,7 @@ static int selector_verify_params(struct comp_dev *dev, /* set component period frames */ sink_c = buffer_acquire(sinkb); - component_set_nearest_period_frames(dev, sink_c->stream.rate); + component_set_nearest_period_frames(dev, audio_stream_get_rate(&sink_c->stream)); buffer_release(sink_c); /* verify input channels */ @@ -402,7 +402,7 @@ static int selector_copy(struct comp_dev *dev) source_c = buffer_acquire(source); - if (!source_c->stream.avail) { + if (!audio_stream_get_avail(&source_c->stream)) { buffer_release(source_c); return PPL_STATUS_PATH_STOP; } @@ -463,11 +463,11 @@ static int selector_prepare(struct comp_dev *dev) sink_c = buffer_acquire(sinkb); /* get source data format and period bytes */ - cd->source_format = source_c->stream.frame_fmt; + cd->source_format = audio_stream_get_frm_fmt(&source_c->stream); cd->source_period_bytes = audio_stream_period_bytes(&source_c->stream, dev->frames); /* get sink data format and period bytes */ - cd->sink_format = sink_c->stream.frame_fmt; + cd->sink_format = audio_stream_get_frm_fmt(&sink_c->stream); cd->sink_period_bytes = audio_stream_period_bytes(&sink_c->stream, dev->frames); /* There is an assumption that sink component will report out @@ -475,11 +475,11 @@ static int selector_prepare(struct comp_dev *dev) * reduce channel count between source and sink */ comp_dbg(dev, "selector_prepare(): sourceb->schannels = %u", - source_c->stream.channels); + audio_stream_get_channels(&source_c->stream)); comp_dbg(dev, "selector_prepare(): sinkb->channels = %u", - sink_c->stream.channels); + audio_stream_get_channels(&sink_c->stream)); - sink_size = sink_c->stream.size; + sink_size = audio_stream_get_size(&sink_c->stream); buffer_release(sink_c); buffer_release(source_c); @@ -576,7 +576,7 @@ SOF_MODULE_INIT(selector, sys_comp_selector_init); #else static void build_config(struct comp_data *cd, struct module_config *cfg) { - enum sof_ipc_frame __sparse_cache frame_fmt, valid_fmt; + enum sof_ipc_frame frame_fmt, valid_fmt; const struct sof_selector_ipc4_config *sel_cfg = &cd->sel_ipc4_cfg; const struct ipc4_audio_format *out_fmt; int i; @@ -697,15 +697,18 @@ static void set_selector_params(struct processing_module *mod, struct comp_buffer *sink_buf = container_of(sink_list, struct comp_buffer, source_list); struct comp_buffer __sparse_cache *sink = buffer_acquire(sink_buf); + enum sof_ipc_frame frame_fmt, valid_fmt; - sink->stream.channels = params->channels; - sink->stream.rate = params->rate; audio_stream_fmt_conversion(out_fmt->depth, out_fmt->valid_bit_depth, - &sink->stream.frame_fmt, - &sink->stream.valid_sample_fmt, + &frame_fmt, &valid_fmt, out_fmt->s_type); + audio_stream_set_frm_fmt(&sink->stream, frame_fmt); + audio_stream_set_valid_fmt(&sink->stream, valid_fmt); + audio_stream_set_channels(&sink->stream, params->channels); + audio_stream_set_rate(&sink->stream, params->rate); + sink->buffer_fmt = out_fmt->interleaving_style; for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) @@ -725,16 +728,19 @@ static void set_selector_params(struct processing_module *mod, source = buffer_acquire(src_buf); if (!source->hw_params_configured) { struct ipc4_audio_format *in_fmt; + enum sof_ipc_frame frame_fmt, valid_fmt; in_fmt = &mod->priv.cfg.base_cfg.audio_fmt; - source->stream.channels = in_fmt->channels_count; - source->stream.rate = in_fmt->sampling_frequency; audio_stream_fmt_conversion(in_fmt->depth, in_fmt->valid_bit_depth, - &source->stream.frame_fmt, - &source->stream.valid_sample_fmt, + &frame_fmt, &valid_fmt, in_fmt->s_type); + audio_stream_set_frm_fmt(&source->stream, frame_fmt); + audio_stream_set_valid_fmt(&source->stream, valid_fmt); + audio_stream_set_channels(&source->stream, in_fmt->channels_count); + audio_stream_set_rate(&source->stream, in_fmt->sampling_frequency); + source->buffer_fmt = in_fmt->interleaving_style; for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) @@ -785,7 +791,7 @@ static int selector_verify_params(struct processing_module *mod, /* set component period frames */ buffer = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); buffer_c = buffer_acquire(buffer); - component_set_nearest_period_frames(dev, buffer_c->stream.rate); + component_set_nearest_period_frames(dev, audio_stream_get_rate(&buffer_c->stream)); buffer_release(buffer_c); return 0; @@ -914,11 +920,11 @@ static int selector_prepare(struct processing_module *mod) audio_stream_init_alignment_constants(4, 1, &sink_c->stream); /* get source data format and period bytes */ - cd->source_format = source_c->stream.frame_fmt; + cd->source_format = audio_stream_get_frm_fmt(&source_c->stream); cd->source_period_bytes = audio_stream_period_bytes(&source_c->stream, dev->frames); /* get sink data format and period bytes */ - cd->sink_format = sink_c->stream.frame_fmt; + cd->sink_format = audio_stream_get_frm_fmt(&sink_c->stream); cd->sink_period_bytes = audio_stream_period_bytes(&sink_c->stream, dev->frames); /* There is an assumption that sink component will report out @@ -926,9 +932,9 @@ static int selector_prepare(struct processing_module *mod) * reduce channel count between source and sink */ comp_info(dev, "selector_prepare(): source sink channel = %u %u", - source_c->stream.channels, sink_c->stream.channels); + audio_stream_get_channels(&source_c->stream), sink_c->stream.channels); - sink_size = sink_c->stream.size; + sink_size = audio_stream_get_size(&sink_c->stream); md->mpd.in_buff_size = cd->source_period_bytes; md->mpd.out_buff_size = cd->sink_period_bytes; diff --git a/src/audio/selector/selector_generic.c b/src/audio/selector/selector_generic.c index 5f2e029b754c..ca9e72f656d5 100644 --- a/src/audio/selector/selector_generic.c +++ b/src/audio/selector/selector_generic.c @@ -36,15 +36,15 @@ static void sel_s16le_1ch(struct comp_dev *dev, struct audio_stream __sparse_cac const struct audio_stream __sparse_cache *source, uint32_t frames) { struct comp_data *cd = comp_get_drvdata(dev); - int16_t *src = source->r_ptr; - int16_t *dest = sink->w_ptr; + int16_t *src = audio_stream_get_rptr(source); + int16_t *dest = audio_stream_get_wptr(sink); int16_t *src_ch; int nmax; int i; int n; int processed = 0; const int source_frame_bytes = audio_stream_frame_bytes(source); - const unsigned int nch = source->channels; + const unsigned int nch = audio_stream_get_channels(source); const unsigned int sel_channel = cd->config.sel_channel; /* 0 to nch - 1 */ while (processed < frames) { @@ -75,8 +75,8 @@ static void sel_s16le_1ch(struct comp_dev *dev, struct audio_stream __sparse_cac static void sel_s16le_nch(struct comp_dev *dev, struct audio_stream __sparse_cache *sink, const struct audio_stream __sparse_cache *source, uint32_t frames) { - int8_t *src = (int8_t *)source->r_ptr; - int8_t *dst = (int8_t *)sink->w_ptr; + int8_t *src = audio_stream_get_rptr(source); + int8_t *dst = audio_stream_get_wptr(sink); int bmax; int b; int bytes_copied = 0; @@ -108,15 +108,15 @@ static void sel_s32le_1ch(struct comp_dev *dev, struct audio_stream __sparse_cac const struct audio_stream __sparse_cache *source, uint32_t frames) { struct comp_data *cd = comp_get_drvdata(dev); - int32_t *src = source->r_ptr; - int32_t *dest = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dest = audio_stream_get_wptr(sink); int32_t *src_ch; int nmax; int i; int n; int processed = 0; const int source_frame_bytes = audio_stream_frame_bytes(source); - const unsigned int nch = source->channels; + const unsigned int nch = audio_stream_get_channels(source); const unsigned int sel_channel = cd->config.sel_channel; /* 0 to nch - 1 */ while (processed < frames) { @@ -147,8 +147,8 @@ static void sel_s32le_1ch(struct comp_dev *dev, struct audio_stream __sparse_cac static void sel_s32le_nch(struct comp_dev *dev, struct audio_stream __sparse_cache *sink, const struct audio_stream __sparse_cache *source, uint32_t frames) { - int8_t *src = (int8_t *)source->r_ptr; - int8_t *dst = (int8_t *)sink->w_ptr; + int8_t *src = audio_stream_get_rptr(source); + int8_t *dst = audio_stream_get_wptr(sink); int bmax; int b; int bytes_copied = 0; @@ -208,16 +208,16 @@ static void sel_s16le(struct processing_module *mod, struct input_stream_buffer struct comp_data *cd = module_get_private_data(mod); struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - int16_t *src = source->r_ptr; - int16_t *dest = sink->w_ptr; + int16_t *src = audio_stream_get_rptr(source); + int16_t *dest = audio_stream_get_wptr(sink); int nmax; int i; int n; int processed = 0; int source_frame_bytes = audio_stream_frame_bytes(source); int sink_frame_bytes = audio_stream_frame_bytes(sink); - int n_chan_source = MIN(SEL_SOURCE_CHANNELS_MAX, source->channels); - int n_chan_sink = MIN(SEL_SINK_CHANNELS_MAX, sink->channels); + int n_chan_source = MIN(SEL_SOURCE_CHANNELS_MAX, audio_stream_get_channels(source)); + int n_chan_sink = MIN(SEL_SINK_CHANNELS_MAX, audio_stream_get_channels(sink)); while (processed < frames) { n = frames - processed; @@ -228,8 +228,8 @@ static void sel_s16le(struct processing_module *mod, struct input_stream_buffer for (i = 0; i < n; i++) { process_frame_s16le(dest, n_chan_sink, src, n_chan_source, &cd->coeffs_config); - src += source->channels; - dest += sink->channels; + src += audio_stream_get_channels(source); + dest += audio_stream_get_channels(sink); } src = audio_stream_wrap(source, src); dest = audio_stream_wrap(sink, dest); @@ -279,16 +279,16 @@ static void sel_s32le(struct processing_module *mod, struct input_stream_buffer struct comp_data *cd = module_get_private_data(mod); struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - int32_t *src = source->r_ptr; - int32_t *dest = sink->w_ptr; + int32_t *src = audio_stream_get_rptr(source); + int32_t *dest = audio_stream_get_wptr(sink); int nmax; int i; int n; int processed = 0; int source_frame_bytes = audio_stream_frame_bytes(source); int sink_frame_bytes = audio_stream_frame_bytes(sink); - int n_chan_source = MIN(SEL_SOURCE_CHANNELS_MAX, source->channels); - int n_chan_sink = MIN(SEL_SINK_CHANNELS_MAX, sink->channels); + int n_chan_source = MIN(SEL_SOURCE_CHANNELS_MAX, audio_stream_get_channels(source)); + int n_chan_sink = MIN(SEL_SINK_CHANNELS_MAX, audio_stream_get_channels(sink)); while (processed < frames) { n = frames - processed; @@ -299,8 +299,8 @@ static void sel_s32le(struct processing_module *mod, struct input_stream_buffer for (i = 0; i < n; i++) { process_frame_s32le(dest, n_chan_sink, src, n_chan_source, &cd->coeffs_config); - src += source->channels; - dest += sink->channels; + src += audio_stream_get_channels(source); + dest += audio_stream_get_channels(sink); } src = audio_stream_wrap(source, src); dest = audio_stream_wrap(sink, dest); diff --git a/src/audio/smart_amp/smart_amp.c b/src/audio/smart_amp/smart_amp.c index 0a4903d8e609..d0108aa346c7 100644 --- a/src/audio/smart_amp/smart_amp.c +++ b/src/audio/smart_amp/smart_amp.c @@ -551,15 +551,19 @@ static int smart_amp_process(struct comp_dev *dev, ret = smart_amp_fb_copy(dev, frames, source, sink, chan_map, sad->mod_handle, - source->channels); + audio_stream_get_channels(source)); return ret; } static smart_amp_proc get_smart_amp_process(struct comp_dev *dev) { struct smart_amp_data *sad = comp_get_drvdata(dev); + struct comp_buffer __sparse_cache *source_buf = buffer_acquire(sad->source_buf); + enum sof_ipc_frame fmt = audio_stream_get_frm_fmt(&source_buf->stream); + + buffer_release(source_buf); - switch (sad->source_buf->stream.frame_fmt) { + switch (fmt) { case SOF_IPC_FRAME_S16_LE: case SOF_IPC_FRAME_S24_4LE: case SOF_IPC_FRAME_S32_LE: @@ -678,7 +682,7 @@ static int smart_amp_prepare(struct comp_dev *dev) sad->feedback_buf = source_buffer; } else { sad->source_buf = source_buffer; - sad->in_channels = source_c->stream.channels; + sad->in_channels = audio_stream_get_channels(&source_c->stream); } buffer_release(source_c); @@ -688,7 +692,7 @@ static int smart_amp_prepare(struct comp_dev *dev) source_list); buf_c = buffer_acquire(sad->sink_buf); - sad->out_channels = buf_c->stream.channels; + sad->out_channels = audio_stream_get_channels(&buf_c->stream); buffer_release(buf_c); source_c = buffer_acquire(sad->source_buf); @@ -696,21 +700,21 @@ static int smart_amp_prepare(struct comp_dev *dev) if (sad->feedback_buf) { buf_c = buffer_acquire(sad->feedback_buf); - buf_c->stream.channels = sad->config.feedback_channels; - buf_c->stream.rate = source_c->stream.rate; + audio_stream_set_channels(&buf_c->stream, sad->config.feedback_channels); + audio_stream_set_rate(&buf_c->stream, audio_stream_get_rate(&source_c->stream)); buffer_release(buf_c); - ret = smart_amp_check_audio_fmt(source_c->stream.rate, - source_c->stream.channels); + ret = smart_amp_check_audio_fmt(audio_stream_get_rate(&source_c->stream), + audio_stream_get_channels(&source_c->stream)); if (ret) { comp_err(dev, "[DSM] Format not supported, sample rate: %d, ch: %d", - source_c->stream.rate, - source_c->stream.channels); + audio_stream_get_rate(&source_c->stream), + audio_stream_get_channels(&source_c->stream)); goto error; } } - switch (source_c->stream.frame_fmt) { + switch (audio_stream_get_frm_fmt(&source_c->stream)) { case SOF_IPC_FRAME_S16_LE: bitwidth = 16; break; @@ -722,7 +726,7 @@ static int smart_amp_prepare(struct comp_dev *dev) break; default: comp_err(dev, "[DSM] smart_amp_process() error: not supported frame format %d", - source_c->stream.frame_fmt); + audio_stream_get_frm_fmt(&source_c->stream)); goto error; } diff --git a/src/audio/smart_amp/smart_amp_generic.c b/src/audio/smart_amp/smart_amp_generic.c index c969f66eadec..3ad4c1ce28de 100644 --- a/src/audio/smart_amp/smart_amp_generic.c +++ b/src/audio/smart_amp/smart_amp_generic.c @@ -35,7 +35,7 @@ static void smart_amp_s16_ff_default(const struct comp_dev *dev, int idx; int ch; int i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); for (ch = 0; ch < nch; ch++) { idx = ch; @@ -63,7 +63,7 @@ static void smart_amp_s24_ff_default(const struct comp_dev *dev, int idx; int ch; int i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); for (ch = 0; ch < nch; ch++) { idx = ch; @@ -90,7 +90,7 @@ static void smart_amp_s32_ff_default(const struct comp_dev *dev, int idx; int ch; int i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); for (ch = 0; ch < nch; ch++) { idx = ch; @@ -115,7 +115,7 @@ static void smart_amp_s16_fb_default(const struct comp_dev *dev, int idx; int ch; int i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); for (ch = 0; ch < nch; ch++) { idx = ch; @@ -139,7 +139,7 @@ static void smart_amp_s24_fb_default(const struct comp_dev *dev, int idx; int ch; int i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); for (ch = 0; ch < nch; ch++) { idx = ch; @@ -163,7 +163,7 @@ static void smart_amp_s32_fb_default(const struct comp_dev *dev, int idx; int ch; int i; - int nch = source->channels; + int nch = audio_stream_get_channels(source); for (ch = 0; ch < nch; ch++) { idx = ch; diff --git a/src/audio/smart_amp/smart_amp_maxim_dsm.c b/src/audio/smart_amp/smart_amp_maxim_dsm.c index 89d7ce372c2b..ed6b5a218511 100644 --- a/src/audio/smart_amp/smart_amp_maxim_dsm.c +++ b/src/audio/smart_amp/smart_amp_maxim_dsm.c @@ -587,12 +587,12 @@ static int smart_amp_get_buffer(int32_t *buf, uint32_t frames, union smart_amp_buf input, output; int index; - input.buf16 = (int16_t *)stream->r_ptr; - input.buf32 = (int32_t *)stream->r_ptr; + input.buf16 = audio_stream_get_rptr(stream); + input.buf32 = audio_stream_get_rptr(stream); output.buf16 = (int16_t *)buf; output.buf32 = (int32_t *)buf; - switch (stream->frame_fmt) { + switch (audio_stream_get_frm_fmt(stream)) { case SOF_IPC_FRAME_S16_LE: for (idx = 0 ; idx < frames ; idx++) { for (ch = 0 ; ch < num_ch; ch++) { @@ -604,7 +604,7 @@ static int smart_amp_get_buffer(int32_t *buf, uint32_t frames, index); output.buf16[num_ch * idx + ch] = *input.buf16; } - in_frag += stream->channels; + in_frag += audio_stream_get_channels(stream); } break; case SOF_IPC_FRAME_S24_4LE: @@ -619,7 +619,7 @@ static int smart_amp_get_buffer(int32_t *buf, uint32_t frames, index); output.buf32[num_ch * idx + ch] = *input.buf32; } - in_frag += stream->channels; + in_frag += audio_stream_get_channels(stream); } break; default: @@ -639,10 +639,10 @@ static int smart_amp_put_buffer(int32_t *buf, uint32_t frames, input.buf16 = (int16_t *)buf; input.buf32 = (int32_t *)buf; - output.buf16 = (int16_t *)stream->w_ptr; - output.buf32 = (int32_t *)stream->w_ptr; + output.buf16 = audio_stream_get_wptr(stream); + output.buf32 = audio_stream_get_wptr(stream); - switch (stream->frame_fmt) { + switch (audio_stream_get_frm_fmt(stream)) { case SOF_IPC_FRAME_S16_LE: for (idx = 0 ; idx < frames ; idx++) { for (ch = 0 ; ch < num_ch_out; ch++) { @@ -708,7 +708,7 @@ int smart_amp_ff_copy(struct comp_dev *dev, uint32_t frames, if (ret) goto err; - switch (source->frame_fmt) { + switch (audio_stream_get_frm_fmt(source)) { case SOF_IPC_FRAME_S16_LE: maxim_dsm_ff_proc(hspk, dev, hspk->buf.frame_in, @@ -767,7 +767,7 @@ int smart_amp_fb_copy(struct comp_dev *dev, uint32_t frames, if (ret) goto err; - switch (source->frame_fmt) { + switch (audio_stream_get_frm_fmt(source)) { case SOF_IPC_FRAME_S16_LE: maxim_dsm_fb_proc(hspk, dev, hspk->buf.frame_iv, frames * num_ch, sizeof(int16_t)); @@ -784,6 +784,6 @@ int smart_amp_fb_copy(struct comp_dev *dev, uint32_t frames, return 0; err: comp_err(dev, "[DSM] Not supported frame format : %d", - source->frame_fmt); + audio_stream_get_frm_fmt(source)); return ret; } diff --git a/src/audio/src/src.c b/src/audio/src/src.c index 513a43735939..193a17746219 100644 --- a/src/audio/src/src.c +++ b/src/audio/src/src.c @@ -69,8 +69,6 @@ struct ipc4_config_src { DECLARE_SOF_RT_UUID("src", src_uuid, 0xe61bb28d, 0x149a, 0x4c1f, 0xb7, 0x09, 0x46, 0x82, 0x3e, 0xf5, 0xf5, 0xae); #elif CONFIG_IPC_MAJOR_3 -static const struct comp_driver comp_src; - /* c1c5326d-8390-46b4-aa47-95c3beca6550 */ DECLARE_SOF_RT_UUID("src", src_uuid, 0xc1c5326d, 0x8390, 0x46b4, 0xaa, 0x47, 0x95, 0xc3, 0xbe, 0xca, 0x65, 0x50); @@ -98,6 +96,7 @@ struct comp_data { int source_frames; int sink_frames; int sample_container_bytes; + int channels_count; void (*src_func)(struct comp_dev *dev, struct comp_data *cd, const struct audio_stream __sparse_cache *source, @@ -358,7 +357,7 @@ static void src_2s(struct comp_dev *dev, struct comp_data *cd, void *sbuf_addr = cd->delay_lines; void *sbuf_end_addr = &cd->delay_lines[cd->param.sbuf_length]; size_t sbuf_size = cd->param.sbuf_length * sizeof(int32_t); - int nch = source->channels; + int nch = audio_stream_get_channels(source); int sbuf_free = cd->param.sbuf_length - cd->sbuf_avail; int avail_b = audio_stream_get_avail_bytes(source); int free_b = audio_stream_get_free_bytes(sink); @@ -366,27 +365,27 @@ static void src_2s(struct comp_dev *dev, struct comp_data *cd, *n_read = 0; *n_written = 0; - s1.x_end_addr = source->end_addr; - s1.x_size = source->size; + s1.x_end_addr = audio_stream_get_end_addr(source); + s1.x_size = audio_stream_get_size(source); s1.y_addr = sbuf_addr; s1.y_end_addr = sbuf_end_addr; s1.y_size = sbuf_size; s1.state = &cd->src.state1; s1.stage = cd->src.stage1; - s1.x_rptr = source->r_ptr; + s1.x_rptr = audio_stream_get_rptr(source); s1.y_wptr = cd->sbuf_w_ptr; s1.nch = nch; s1.shift = cd->data_shift; s2.x_end_addr = sbuf_end_addr; s2.x_size = sbuf_size; - s2.y_addr = sink->addr; - s2.y_end_addr = sink->end_addr; - s2.y_size = sink->size; + s2.y_addr = audio_stream_get_addr(sink); + s2.y_end_addr = audio_stream_get_end_addr(sink); + s2.y_size = audio_stream_get_size(sink); s2.state = &cd->src.state2; s2.stage = cd->src.stage2; s2.x_rptr = cd->sbuf_r_ptr; - s2.y_wptr = sink->w_ptr; + s2.y_wptr = audio_stream_get_wptr(sink); s2.nch = nch; s2.shift = cd->data_shift; @@ -442,15 +441,15 @@ static void src_1s(struct comp_dev *dev, struct comp_data *cd, struct src_stage_prm s1; s1.times = cd->param.stage1_times; - s1.x_rptr = source->r_ptr; - s1.x_end_addr = source->end_addr; - s1.x_size = source->size; - s1.y_wptr = sink->w_ptr; - s1.y_end_addr = sink->end_addr; - s1.y_size = sink->size; + s1.x_rptr = audio_stream_get_rptr(source); + s1.x_end_addr = audio_stream_get_end_addr(source); + s1.x_size = audio_stream_get_size(source); + s1.y_wptr = audio_stream_get_wptr(sink); + s1.y_end_addr = audio_stream_get_end_addr(sink); + s1.y_size = audio_stream_get_size(sink); s1.state = &cd->src.state1; s1.stage = cd->src.stage1; - s1.nch = source->channels; + s1.nch = audio_stream_get_channels(source); s1.shift = cd->data_shift; cd->polyphase_func(&s1); @@ -467,12 +466,12 @@ static void src_copy_sxx(struct comp_dev *dev, struct comp_data *cd, { int frames = cd->param.blk_in; - switch (sink->frame_fmt) { + switch (audio_stream_get_frm_fmt(sink)) { case SOF_IPC_FRAME_S16_LE: case SOF_IPC_FRAME_S24_4LE: case SOF_IPC_FRAME_S32_LE: audio_stream_copy(source, 0, sink, 0, - frames * source->channels); + frames * audio_stream_get_channels(source)); *n_read = frames; *n_written = frames; break; @@ -487,7 +486,7 @@ static int src_rate_check(const void *spec) { const struct ipc4_config_src *ipc_src = spec; - if (ipc_src->base.audio_fmt.sampling_frequency == 0 && ipc_src->sink_rate == 0) + if (ipc_src->base.audio_fmt.sampling_frequency == 0 || ipc_src->sink_rate == 0) return -EINVAL; return 0; @@ -496,8 +495,14 @@ static int src_rate_check(const void *spec) static int src_stream_pcm_source_rate_check(struct ipc4_config_src cfg, struct sof_ipc_stream_params *params) { - if (cfg.base.audio_fmt.sampling_frequency && - params->rate != cfg.base.audio_fmt.sampling_frequency) + /* Nothing to check */ + return 0; +} + +static int src_stream_pcm_sink_rate_check(struct ipc4_config_src cfg, + struct sof_ipc_stream_params *params) +{ + if (cfg.sink_rate && params->rate != cfg.sink_rate) return -EINVAL; return 0; @@ -507,62 +512,58 @@ static int src_stream_pcm_source_rate_check(struct ipc4_config_src cfg, * set up param then verify param. BTW for IPC3 path, the param is sent by * host driver. */ -static void src_set_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) +static int src_set_params(struct processing_module *mod) { - struct processing_module *mod = comp_get_drvdata(dev); + struct sof_ipc_stream_params src_params; + struct sof_ipc_stream_params *params = mod->stream_params; struct comp_data *cd = module_get_private_data(mod); + enum sof_ipc_frame frame_fmt, valid_fmt; + struct comp_dev *dev = mod->dev; struct comp_buffer *sinkb; struct comp_buffer __sparse_cache *sink_c; + int ret; + + src_params = *params; + src_params.channels = mod->priv.cfg.base_cfg.audio_fmt.channels_count; + src_params.buffer_fmt = mod->priv.cfg.base_cfg.audio_fmt.interleaving_style; + src_params.rate = cd->ipc_config.sink_rate; - memset(params, 0, sizeof(*params)); - params->channels = cd->ipc_config.base.audio_fmt.channels_count; - params->rate = cd->ipc_config.base.audio_fmt.sampling_frequency; - params->sample_container_bytes = cd->ipc_config.base.audio_fmt.depth / 8; - params->sample_valid_bytes = cd->ipc_config.base.audio_fmt.valid_bit_depth / 8; - params->frame_fmt = dev->ipc_config.frame_fmt; - params->buffer_fmt = cd->ipc_config.base.audio_fmt.interleaving_style; - params->buffer.size = cd->ipc_config.base.ibs; + /* Get frame_fmt and valid_fmt */ + audio_stream_fmt_conversion(mod->priv.cfg.base_cfg.audio_fmt.depth, + mod->priv.cfg.base_cfg.audio_fmt.valid_bit_depth, + &frame_fmt, &valid_fmt, + mod->priv.cfg.base_cfg.audio_fmt.s_type); + + src_params.frame_fmt = frame_fmt; + component_set_nearest_period_frames(dev, src_params.rate); sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); sink_c = buffer_acquire(sinkb); - sink_c->stream.rate = cd->ipc_config.sink_rate; + ret = buffer_set_params(sink_c, &src_params, true); buffer_release(sink_c); + + /* Update module stream_params */ + params->rate = cd->ipc_config.sink_rate; + return ret; } static void src_set_sink_params(struct comp_dev *dev, struct comp_buffer __sparse_cache *sinkb) { struct processing_module *mod = comp_get_drvdata(dev); struct comp_data *cd = module_get_private_data(mod); + enum sof_ipc_frame frame_fmt, valid_fmt; /* convert IPC4 config to format used by the module */ audio_stream_fmt_conversion(cd->ipc_config.base.audio_fmt.depth, cd->ipc_config.base.audio_fmt.valid_bit_depth, - &sinkb->stream.frame_fmt, - &sinkb->stream.valid_sample_fmt, + &frame_fmt, &valid_fmt, cd->ipc_config.base.audio_fmt.s_type); - sinkb->stream.channels = cd->ipc_config.base.audio_fmt.channels_count; - sinkb->buffer_fmt = cd->ipc_config.base.audio_fmt.interleaving_style; -} -static inline void src_update_buffer_position(struct input_stream_buffer *input_buffers, - struct output_stream_buffer *output_buffers, - int *n_read, int *n_written) -{ - struct audio_stream __sparse_cache *source = input_buffers->data; - struct audio_stream __sparse_cache *sink = output_buffers->data; - - input_buffers->consumed += audio_stream_frame_bytes(source) * (*n_read); - output_buffers->size += audio_stream_frame_bytes(sink) * (*n_written); -} - -static void src_set_alignment(struct audio_stream __sparse_cache *source, - struct audio_stream __sparse_cache *sink) -{ - const uint32_t byte_align = 1; - const uint32_t frame_align_req = 1; + audio_stream_set_frm_fmt(&sinkb->stream, frame_fmt); + audio_stream_set_valid_fmt(&sinkb->stream, valid_fmt); + audio_stream_set_channels(&sinkb->stream, cd->ipc_config.base.audio_fmt.channels_count); - audio_stream_init_alignment_constants(byte_align, frame_align_req, source); - audio_stream_init_alignment_constants(byte_align, frame_align_req, sink); + sinkb->buffer_fmt = cd->ipc_config.base.audio_fmt.interleaving_style; } #elif CONFIG_IPC_MAJOR_3 @@ -576,25 +577,62 @@ static int src_rate_check(const void *spec) return 0; } +static int src_stream_pcm_sink_rate_check(struct ipc_config_src cfg, + struct sof_ipc_stream_params *params) +{ + /* In playback, module adapter mod->stream_params from prepare() is for sink side */ + if (cfg.sink_rate && params->rate != cfg.sink_rate) + return -EINVAL; + + return 0; +} + static int src_stream_pcm_source_rate_check(struct ipc_config_src cfg, struct sof_ipc_stream_params *params) { + /* In capture, module adapter mod->stream_params from prepare() is for source side */ if (cfg.source_rate && params->rate != cfg.source_rate) return -EINVAL; return 0; } -static void src_set_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) {} +static int src_set_params(struct processing_module *mod) +{ + return 0; +} static void src_set_sink_params(struct comp_dev *dev, struct comp_buffer __sparse_cache *sinkb) {} #else #error "No or invalid IPC MAJOR version selected." #endif /* CONFIG_IPC_MAJOR_4 */ -static int src_verify_params(struct comp_dev *dev, struct comp_data *cd, - struct sof_ipc_stream_params *params) +static inline void src_update_buffer_position(struct input_stream_buffer *input_buffers, + struct output_stream_buffer *output_buffers, + int *n_read, int *n_written) +{ + struct audio_stream __sparse_cache *source = input_buffers->data; + struct audio_stream __sparse_cache *sink = output_buffers->data; + + input_buffers->consumed += audio_stream_frame_bytes(source) * (*n_read); + output_buffers->size += audio_stream_frame_bytes(sink) * (*n_written); +} + +static void src_set_alignment(struct audio_stream __sparse_cache *source, + struct audio_stream __sparse_cache *sink) +{ + const uint32_t byte_align = 1; + const uint32_t frame_align_req = 1; + + audio_stream_init_alignment_constants(byte_align, frame_align_req, source); + audio_stream_init_alignment_constants(byte_align, frame_align_req, sink); +} + +static int src_verify_params(struct processing_module *mod) { + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; int ret; comp_dbg(dev, "src_verify_params()"); @@ -605,16 +643,16 @@ static int src_verify_params(struct comp_dev *dev, struct comp_data *cd, * src->source/sink_rate = 0 means that source/sink rate can vary. */ if (dev->direction == SOF_IPC_STREAM_PLAYBACK) { - ret = src_stream_pcm_source_rate_check(cd->ipc_config, params); + ret = src_stream_pcm_sink_rate_check(cd->ipc_config, params); if (ret < 0) { - comp_err(dev, "src_verify_params(): runtime stream pcm rate does not match rate fetched from ipc."); + comp_err(dev, "src_verify_params(): sink stream rate does not match rate fetched from ipc."); return ret; } } else { - if (cd->ipc_config.sink_rate && params->rate != cd->ipc_config.sink_rate) { - comp_err(dev, "src_verify_params(): runtime stream pcm rate %u does not match rate %u fetched from ipc.", - params->rate, cd->ipc_config.sink_rate); - return -EINVAL; + ret = src_stream_pcm_source_rate_check(cd->ipc_config, params); + if (ret < 0) { + comp_err(dev, "src_verify_params(): source stream rate does not match rate fetched from ipc."); + return ret; } } @@ -701,23 +739,24 @@ static int src_check_buffer_sizes(struct comp_dev *dev, struct comp_data *cd, } n = audio_stream_frame_bytes(source_stream) * (blk_in + cd->source_frames); - if (source_stream->size < n) { + if (audio_stream_get_size(source_stream) < n) { comp_warn(dev, "Source size %d is less than required %d", - source_stream->size, n); + audio_stream_get_size(source_stream), n); } n = audio_stream_frame_bytes(sink_stream) * (blk_out + cd->sink_frames); - if (sink_stream->size < n) { + if (audio_stream_get_size(sink_stream) < n) { comp_warn(dev, "Sink size %d is less than required %d", - sink_stream->size, n); + audio_stream_get_size(sink_stream), n); } return 0; } -static int src_params_general(struct comp_dev *dev, struct comp_data *cd, - struct sof_ipc_stream_params *params) +static int src_params_general(struct processing_module *mod) { + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; struct comp_buffer *sourceb, *sinkb; struct comp_buffer __sparse_cache *source_c, *sink_c; size_t delay_lines_size; @@ -727,32 +766,38 @@ static int src_params_general(struct comp_dev *dev, struct comp_data *cd, comp_info(dev, "src_params()"); - src_set_params(dev, params); - err = src_verify_params(dev, cd, params); + err = src_set_params(mod); if (err < 0) { - comp_err(dev, "src_params(): pcm params verification failed."); - return -EINVAL; + comp_err(dev, "src_params(): set params failed."); + return err; } - cd->sample_container_bytes = params->sample_container_bytes; + err = src_verify_params(mod); + if (err < 0) { + comp_err(dev, "src_params(): pcm params verification failed."); + return err; + } /* src components will only ever have 1 source and 1 sink buffer */ - sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); - sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - + sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); + sinkb = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); source_c = buffer_acquire(sourceb); sink_c = buffer_acquire(sinkb); - src_set_sink_params(dev, sink_c); +#if CONFIG_IPC_MAJOR_3 /* Set source/sink_rate/frames */ - cd->source_rate = source_c->stream.rate; - cd->sink_rate = sink_c->stream.rate; + cd->channels_count = audio_stream_get_channels(&source_c->stream); + cd->source_rate = audio_stream_get_rate(&source_c->stream); + cd->sink_rate = audio_stream_get_rate(&sink_c->stream); + cd->sample_container_bytes = mod->stream_params->sample_container_bytes; +#endif + comp_info(dev, "src_params(), source_rate = %u, sink_rate = %u", + cd->source_rate, cd->sink_rate); + comp_dbg(dev, "src_params(), sample_container_bytes = %d, channels = %u, dev->frames = %u", + cd->sample_container_bytes, cd->channels_count, dev->frames); if (!cd->sink_rate) { comp_err(dev, "src_params(), zero sink rate"); - err = -EINVAL; goto out; } @@ -761,11 +806,7 @@ static int src_params_general(struct comp_dev *dev, struct comp_data *cd, cd->sink_frames = dev->frames; /* Allocate needed memory for delay lines */ - comp_info(dev, "src_params(), source_rate = %u, sink_rate = %u, format = %d", - cd->source_rate, cd->sink_rate, source_c->stream.frame_fmt); - comp_info(dev, "src_params(), sourceb->channels = %u, sinkb->channels = %u, dev->frames = %u", - source_c->stream.channels, sink_c->stream.channels, dev->frames); - err = src_buffer_lengths(dev, cd, source_c->stream.channels); + err = src_buffer_lengths(dev, cd, cd->channels_count); if (err < 0) { comp_err(dev, "src_params(): src_buffer_lengths() failed"); goto out; @@ -834,13 +875,17 @@ static int src_params_general(struct comp_dev *dev, struct comp_data *cd, return err; } -static int src_prepare_general(struct comp_dev *dev, struct comp_data *cd) +static int src_prepare_general(struct processing_module *mod) { + struct comp_data *cd = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; struct comp_buffer *sourceb, *sinkb; struct comp_buffer __sparse_cache *source_c, *sink_c; + int ret; +#if CONFIG_IPC_MAJOR_3 enum sof_ipc_frame source_format; enum sof_ipc_frame sink_format; - int ret; +#endif /* SRC component will only ever have 1 source and 1 sink buffer */ sourceb = list_first_item(&dev->bsource_list, @@ -851,19 +896,44 @@ static int src_prepare_general(struct comp_dev *dev, struct comp_data *cd) source_c = buffer_acquire(sourceb); sink_c = buffer_acquire(sinkb); -#if CONFIG_IPC_MAJOR_4 /* set align requirements */ src_set_alignment(&source_c->stream, &sink_c->stream); -#endif - - /* get source/sink data format */ - source_format = source_c->stream.frame_fmt; - sink_format = sink_c->stream.frame_fmt; ret = src_check_buffer_sizes(dev, cd, &source_c->stream, &sink_c->stream); if (ret < 0) goto out; +#if CONFIG_IPC_MAJOR_4 + switch (cd->ipc_config.base.audio_fmt.depth) { +#if CONFIG_FORMAT_S16LE + case IPC4_DEPTH_16BIT: + cd->data_shift = 0; + cd->polyphase_func = src_polyphase_stage_cir_s16; + break; +#endif /* CONFIG_FORMAT_S16LE */ +#if CONFIG_FORMAT_S24LE + case IPC4_DEPTH_24BIT: + cd->data_shift = 8; + cd->polyphase_func = src_polyphase_stage_cir; + break; +#endif /* CONFIG_FORMAT_S24LE */ +#if CONFIG_FORMAT_S32LE + case IPC4_DEPTH_32BIT: + cd->data_shift = 0; + cd->polyphase_func = src_polyphase_stage_cir; + break; +#endif /* CONFIG_FORMAT_S32LE */ + default: + comp_err(dev, "src_prepare(): Invalid depth %d", + cd->ipc_config.base.audio_fmt.depth); + ret = -EINVAL; + goto out; + } +#elif CONFIG_IPC_MAJOR_3 + /* get source/sink data format */ + source_format = audio_stream_get_frm_fmt(&source_c->stream); + sink_format = audio_stream_get_frm_fmt(&sink_c->stream); + /* SRC supports S16_LE, S24_4LE and S32_LE formats */ if (source_format != sink_format) { comp_err(dev, "src_prepare(): Source fmt %d and sink fmt %d are different.", @@ -896,6 +966,7 @@ static int src_prepare_general(struct comp_dev *dev, struct comp_data *cd) ret = -EINVAL; goto out; } +#endif /* CONFIG_IPC_MAJOR_3 */ out: if (ret < 0) @@ -907,7 +978,6 @@ static int src_prepare_general(struct comp_dev *dev, struct comp_data *cd) return ret; } -#if CONFIG_IPC_MAJOR_4 static int src_init(struct processing_module *mod) { struct module_data *md = &mod->priv; @@ -924,11 +994,10 @@ static int src_init(struct processing_module *mod) } cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - if (!cd) { - rfree(dev); + if (!cd) return -ENOMEM; - } + md->private = cd; memcpy_s(&cd->ipc_config, sizeof(cd->ipc_config), cfg->init_data, sizeof(cd->ipc_config)); cd->delay_lines = NULL; @@ -936,7 +1005,32 @@ static int src_init(struct processing_module *mod) cd->polyphase_func = NULL; src_polyphase_reset(&cd->src); - md->private = cd; +#if CONFIG_IPC_MAJOR_4 + comp_dbg(dev, "src_init(), channels_count = %d, depth = %d", + cd->ipc_config.base.audio_fmt.channels_count, + cd->ipc_config.base.audio_fmt.depth); + comp_dbg(dev, "src_init(), sampling frequency = %d, sink rate = %d", + cd->ipc_config.base.audio_fmt.sampling_frequency, cd->ipc_config.sink_rate); + cd->source_rate = cd->ipc_config.base.audio_fmt.sampling_frequency; + cd->sink_rate = cd->ipc_config.sink_rate; + cd->channels_count = cd->ipc_config.base.audio_fmt.channels_count; + switch (cd->ipc_config.base.audio_fmt.depth) { + case IPC4_DEPTH_16BIT: + cd->sample_container_bytes = sizeof(int16_t); + break; + case IPC4_DEPTH_24BIT: + case IPC4_DEPTH_32BIT: + cd->sample_container_bytes = sizeof(int32_t); + break; + default: + comp_err(dev, "src_init(): Illegal sample depth %d", + cd->ipc_config.base.audio_fmt.depth); + rfree(cd); + return -EINVAL; + } +#elif CONFIG_IPC_MAJOR_3 + mod->verify_params_flags = BUFF_PARAMS_RATE; +#endif mod->simple_copy = true; @@ -945,18 +1039,15 @@ static int src_init(struct processing_module *mod) static int src_prepare(struct processing_module *mod) { - struct comp_data *cd = module_get_private_data(mod); - struct sof_ipc_stream_params *params = mod->stream_params; - struct comp_dev *dev = mod->dev; int ret; - comp_info(dev, "src_prepare()"); + comp_info(mod->dev, "src_prepare()"); - ret = src_params_general(dev, cd, params); + ret = src_params_general(mod); if (ret < 0) return ret; - return src_prepare_general(dev, cd); + return src_prepare_general(mod); } static int src_process(struct processing_module *mod, @@ -965,18 +1056,15 @@ static int src_process(struct processing_module *mod, { struct comp_data *cd = module_get_private_data(mod); struct comp_dev *dev = mod->dev; - struct audio_stream __sparse_cache *source_c, *sink_c; - + /* src component needs 1 source and 1 sink buffer */ + struct audio_stream __sparse_cache *source_c = input_buffers[0].data; + struct audio_stream __sparse_cache *sink_c = output_buffers[0].data; int consumed = 0; int produced = 0; int ret; comp_dbg(dev, "src_process()"); - /* src component needs 1 source and 1 sink buffer */ - source_c = (struct audio_stream *)input_buffers[0].data; - sink_c = (struct audio_stream *)output_buffers[0].data; - ret = src_get_copy_limits(cd, source_c, sink_c); if (ret) { comp_dbg(dev, "No data to process."); @@ -1042,218 +1130,3 @@ static struct module_interface src_interface = { DECLARE_MODULE_ADAPTER(src_interface, src_uuid, src_tr); SOF_MODULE_INIT(src, sys_comp_module_src_interface_init); - -#elif CONFIG_IPC_MAJOR_3 -static struct comp_dev *src_new(const struct comp_driver *drv, - const struct comp_ipc_config *config, - const void *spec) -{ - struct comp_dev *dev; - struct comp_data *cd; - - comp_cl_info(&comp_src, "src_new()"); - - /* validate init data - either SRC sink or source rate must be set */ - if (src_rate_check(spec) < 0) { - comp_cl_err(&comp_src, "src_new(): SRC sink and source rate are not set"); - return NULL; - } - - dev = comp_alloc(drv, sizeof(*dev)); - if (!dev) - return NULL; - dev->ipc_config = *config; - - cd = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*cd)); - if (!cd) { - rfree(dev); - return NULL; - } - - comp_set_drvdata(dev, cd); - memcpy_s(&cd->ipc_config, sizeof(cd->ipc_config), spec, sizeof(cd->ipc_config)); - - cd->delay_lines = NULL; - cd->src_func = src_fallback; - cd->polyphase_func = NULL; - src_polyphase_reset(&cd->src); - - dev->state = COMP_STATE_READY; - return dev; -} - -static void src_free(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "src_free()"); - - /* Free dynamically reserved buffers for SRC algorithm */ - rfree(cd->delay_lines); - - rfree(cd); - rfree(dev); -} - -/* set component audio stream parameters */ -static int src_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - return src_params_general(dev, cd, params); -} - -static int src_ctrl_cmd(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) -{ - comp_err(dev, "src_ctrl_cmd()"); - return -EINVAL; -} - -/* used to pass standard and bespoke commands (with data) to component */ -static int src_cmd(struct comp_dev *dev, int cmd, void *data, - int max_data_size) -{ - struct sof_ipc_ctrl_data *cdata = ASSUME_ALIGNED(data, 4); - int ret = 0; - - comp_info(dev, "src_cmd()"); - - if (cmd == COMP_CMD_SET_VALUE) - ret = src_ctrl_cmd(dev, cdata); - - return ret; -} - -static int src_trigger(struct comp_dev *dev, int cmd) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "src_trigger()"); - - if (cmd == COMP_TRIGGER_START || cmd == COMP_TRIGGER_RELEASE) { - if (!cd->polyphase_func) { - comp_err(dev, "polyphase_func is not set"); - return -EINVAL; - } - } - return comp_set_state(dev, cmd); -} - -static void src_process(struct comp_dev *dev, struct comp_buffer __sparse_cache *source, - struct comp_buffer __sparse_cache *sink) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int consumed = 0; - int produced = 0; - - /* consumed bytes are not known at this point */ - buffer_stream_invalidate(source, source->stream.size); - cd->src_func(dev, cd, &source->stream, &sink->stream, &consumed, &produced); - buffer_stream_writeback(sink, produced * audio_stream_frame_bytes(&sink->stream)); - - comp_dbg(dev, "src_copy(), consumed = %u, produced = %u", - consumed, produced); - - comp_update_buffer_consume(source, consumed * - audio_stream_frame_bytes(&source->stream)); - comp_update_buffer_produce(sink, produced * - audio_stream_frame_bytes(&sink->stream)); -} - -/* copy and process stream data from source to sink buffers */ -static int src_copy(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - struct comp_buffer *source, *sink; - struct comp_buffer __sparse_cache *source_c, *sink_c; - int ret; - - comp_dbg(dev, "src_copy()"); - - /* src component needs 1 source and 1 sink buffer */ - source = list_first_item(&dev->bsource_list, struct comp_buffer, - sink_list); - sink = list_first_item(&dev->bsink_list, struct comp_buffer, - source_list); - - source_c = buffer_acquire(source); - sink_c = buffer_acquire(sink); - - /* Get from buffers and SRC conversion specific block constraints - * how many frames can be processed. If sufficient number of samples - * is not available the processing is omitted. - */ - ret = src_get_copy_limits(cd, &source_c->stream, &sink_c->stream); - if (ret) - comp_dbg(dev, "No data to process."); - else - src_process(dev, source_c, sink_c); - - buffer_release(sink_c); - buffer_release(source_c); - - return 0; -} - -static int src_prepare(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - int ret; - - comp_info(dev, "src_prepare()"); - - ret = comp_set_state(dev, COMP_TRIGGER_PREPARE); - if (ret < 0) - return ret; - - if (ret == COMP_STATUS_STATE_ALREADY_SET) - return PPL_STATUS_PATH_STOP; - - return src_prepare_general(dev, cd); -} - -static int src_reset(struct comp_dev *dev) -{ - struct comp_data *cd = comp_get_drvdata(dev); - - comp_info(dev, "src_reset()"); - - cd->src_func = src_fallback; - src_polyphase_reset(&cd->src); - - comp_set_state(dev, COMP_TRIGGER_RESET); - return 0; -} - -static const struct comp_driver comp_src = { - .type = SOF_COMP_SRC, - .uid = SOF_RT_UUID(src_uuid), - .tctx = &src_tr, - .ops = { - .create = src_new, - .free = src_free, - .params = src_params, - .cmd = src_cmd, - .trigger = src_trigger, - .copy = src_copy, - .prepare = src_prepare, - .reset = src_reset, - }, -}; - -static SHARED_DATA struct comp_driver_info comp_src_info = { - .drv = &comp_src, -}; - -UT_STATIC void sys_comp_src_init(void) -{ - comp_register(platform_shared_get(&comp_src_info, - sizeof(comp_src_info))); -} - -DECLARE_MODULE(sys_comp_src_init); -SOF_MODULE_INIT(src, sys_comp_src_init); -#else -#error "No or invalid IPC MAJOR version selected." -#endif diff --git a/src/audio/tdfb/tdfb.c b/src/audio/tdfb/tdfb.c index 8e710533a1c2..c2f395ed7698 100644 --- a/src/audio/tdfb/tdfb.c +++ b/src/audio/tdfb/tdfb.c @@ -671,7 +671,8 @@ static int tdfb_process(struct processing_module *mod, /* Check for changed configuration */ if (comp_is_new_data_blob_available(cd->model_handler)) { cd->config = comp_get_data_blob(cd->model_handler, NULL, NULL); - ret = tdfb_setup(mod, source->channels, sink->channels); + ret = tdfb_setup(mod, audio_stream_get_channels(source), + audio_stream_get_channels(sink)); if (ret < 0) { comp_err(dev, "tdfb_process(), failed FIR setup"); return ret; @@ -681,7 +682,8 @@ static int tdfb_process(struct processing_module *mod, /* Handle enum controls */ if (cd->update) { cd->update = false; - ret = tdfb_setup(mod, source->channels, sink->channels); + ret = tdfb_setup(mod, audio_stream_get_channels(source), + audio_stream_get_channels(sink)); if (ret < 0) { comp_err(dev, "tdfb_process(), failed FIR setup"); return ret; @@ -699,7 +701,7 @@ static int tdfb_process(struct processing_module *mod, module_update_buffer_position(input_buffers, output_buffers, frame_count); /* Update sound direction estimate */ - tdfb_direction_estimate(cd, frame_count, source->channels); + tdfb_direction_estimate(cd, frame_count, audio_stream_get_channels(source)); comp_dbg(dev, "tdfb_dint %u %d %d %d", cd->direction.trigger, cd->direction.level, (int32_t)(cd->direction.level_ambient >> 32), cd->direction.az_slow); @@ -745,10 +747,10 @@ static int tdfb_prepare(struct processing_module *mod) sink_c = buffer_acquire(sinkb); tdfb_set_alignment(&source_c->stream, &sink_c->stream); - frame_fmt = source_c->stream.frame_fmt; - source_channels = source_c->stream.channels; - sink_channels = sink_c->stream.channels; - rate = source_c->stream.rate; + frame_fmt = audio_stream_get_frm_fmt(&source_c->stream); + source_channels = audio_stream_get_channels(&source_c->stream); + sink_channels = audio_stream_get_channels(&sink_c->stream); + rate = audio_stream_get_rate(&source_c->stream); buffer_release(sink_c); buffer_release(source_c); diff --git a/src/audio/tdfb/tdfb_generic.c b/src/audio/tdfb/tdfb_generic.c index 5f2d345204df..8306bb6a8991 100644 --- a/src/audio/tdfb/tdfb_generic.c +++ b/src/audio/tdfb/tdfb_generic.c @@ -60,14 +60,14 @@ void tdfb_fir_s16(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource { struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - int16_t *x = source->r_ptr; - int16_t *y = sink->w_ptr; + int16_t *x = audio_stream_get_rptr(source); + int16_t *y = audio_stream_get_wptr(sink); int fmax; int i; int j; int f; - const int in_nch = source->channels; - const int out_nch = sink->channels; + const int in_nch = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); int remaining_frames = frames; int emp_ch = 0; @@ -106,14 +106,14 @@ void tdfb_fir_s24(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource { struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); int fmax; int i; int j; int f; - const int in_nch = source->channels; - const int out_nch = sink->channels; + const int in_nch = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); int remaining_frames = frames; int emp_ch = 0; @@ -152,14 +152,14 @@ void tdfb_fir_s32(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource { struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); int fmax; int i; int j; int f; - const int in_nch = source->channels; - const int out_nch = sink->channels; + const int in_nch = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); int remaining_frames = frames; int emp_ch = 0; diff --git a/src/audio/tdfb/tdfb_hifi3.c b/src/audio/tdfb/tdfb_hifi3.c index 8c667e53474d..2109431d7993 100644 --- a/src/audio/tdfb/tdfb_hifi3.c +++ b/src/audio/tdfb/tdfb_hifi3.c @@ -26,8 +26,8 @@ void tdfb_fir_s16(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource ae_int16x4 d; ae_int32 y0; ae_int32 y1; - ae_int16 *x = (ae_int16 *)source->r_ptr; - ae_int16 *y = (ae_int16 *)sink->w_ptr; + ae_int16 *x = audio_stream_get_rptr(source); + ae_int16 *y = audio_stream_get_wptr(sink); int shift; int is2; int is; @@ -35,8 +35,8 @@ void tdfb_fir_s16(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource int i; int j; int k; - int in_nch = source->channels; - int out_nch = sink->channels; + int in_nch = audio_stream_get_channels(source); + int out_nch = audio_stream_get_channels(sink); int emp_ch = 0; for (j = 0; j < (frames >> 1); j++) { @@ -101,8 +101,8 @@ void tdfb_fir_s24(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource ae_int32x2 d; ae_int32 y0; ae_int32 y1; - ae_int32 *x = (ae_int32 *)source->r_ptr; - ae_int32 *y = (ae_int32 *)sink->w_ptr; + ae_int32 *x = audio_stream_get_rptr(source); + ae_int32 *y = audio_stream_get_wptr(sink); int shift; int is2; int is; @@ -110,8 +110,8 @@ void tdfb_fir_s24(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource int i; int j; int k; - int in_nch = source->channels; - int out_nch = sink->channels; + int in_nch = audio_stream_get_channels(source); + int out_nch = audio_stream_get_channels(sink); int emp_ch = 0; for (j = 0; j < (frames >> 1); j++) { @@ -175,8 +175,8 @@ void tdfb_fir_s32(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource ae_int32x2 d; ae_int32 y0; ae_int32 y1; - ae_int32 *x = (ae_int32 *)source->r_ptr; - ae_int32 *y = (ae_int32 *)sink->w_ptr; + ae_int32 *x = audio_stream_get_rptr(source); + ae_int32 *y = audio_stream_get_wptr(sink); int shift; int is2; int is; @@ -184,8 +184,8 @@ void tdfb_fir_s32(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource int i; int j; int k; - int in_nch = source->channels; - int out_nch = sink->channels; + int in_nch = audio_stream_get_channels(source); + int out_nch = audio_stream_get_channels(sink); int emp_ch = 0; for (j = 0; j < (frames >> 1); j++) { diff --git a/src/audio/tdfb/tdfb_hifiep.c b/src/audio/tdfb/tdfb_hifiep.c index 4c1ac290f45d..eba8d7c7807e 100644 --- a/src/audio/tdfb/tdfb_hifiep.c +++ b/src/audio/tdfb/tdfb_hifiep.c @@ -60,14 +60,14 @@ void tdfb_fir_s16(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource { struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - int16_t *x = source->r_ptr; - int16_t *y = sink->w_ptr; + int16_t *x = audio_stream_get_rptr(source); + int16_t *y = audio_stream_get_wptr(sink); int fmax; int i; int j; int f; - const int in_nch = source->channels; - const int out_nch = sink->channels; + const int in_nch = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); int remaining_frames = frames; int emp_ch = 0; @@ -106,14 +106,14 @@ void tdfb_fir_s24(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource { struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); int fmax; int i; int j; int f; - const int in_nch = source->channels; - const int out_nch = sink->channels; + const int in_nch = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); int remaining_frames = frames; int emp_ch = 0; @@ -152,14 +152,14 @@ void tdfb_fir_s32(struct tdfb_comp_data *cd, struct input_stream_buffer *bsource { struct audio_stream __sparse_cache *source = bsource->data; struct audio_stream __sparse_cache *sink = bsink->data; - int32_t *x = source->r_ptr; - int32_t *y = sink->w_ptr; + int32_t *x = audio_stream_get_rptr(source); + int32_t *y = audio_stream_get_wptr(sink); int fmax; int i; int j; int f; - const int in_nch = source->channels; - const int out_nch = sink->channels; + const int in_nch = audio_stream_get_channels(source); + const int out_nch = audio_stream_get_channels(sink); int remaining_frames = frames; int emp_ch = 0; diff --git a/src/audio/tone.c b/src/audio/tone.c index 346f4807decd..65c934246909 100644 --- a/src/audio/tone.c +++ b/src/audio/tone.c @@ -117,7 +117,7 @@ static void tone_s32_default(struct comp_dev *dev, struct audio_stream __sparse_ uint32_t frames) { struct comp_data *cd = comp_get_drvdata(dev); - int32_t *dest = (int32_t *)sink->w_ptr; + int32_t *dest = audio_stream_get_wptr(sink); int i; int n; int n_wrap_dest; @@ -126,7 +126,7 @@ static void tone_s32_default(struct comp_dev *dev, struct audio_stream __sparse_ n = frames * nch; while (n > 0) { - n_wrap_dest = (int32_t *)sink->end_addr - dest; + n_wrap_dest = (int32_t *)audio_stream_get_end_addr(sink) - dest; n_min = (n < n_wrap_dest) ? n : n_wrap_dest; /* Process until wrap or completed n */ while (n_min > 0) { @@ -138,7 +138,8 @@ static void tone_s32_default(struct comp_dev *dev, struct audio_stream __sparse_ dest++; } } - tone_circ_inc_wrap(&dest, sink->end_addr, sink->size); + tone_circ_inc_wrap(&dest, audio_stream_get_end_addr(sink), + audio_stream_get_size(sink)); } } @@ -446,8 +447,8 @@ static int tone_params(struct comp_dev *dev, source_c = buffer_acquire(sourceb); sink_c = buffer_acquire(sinkb); - source_c->stream.frame_fmt = dev->ipc_config.frame_fmt; - sink_c->stream.frame_fmt = dev->ipc_config.frame_fmt; + audio_stream_set_frm_fmt(&source_c->stream, dev->ipc_config.frame_fmt); + audio_stream_set_frm_fmt(&sink_c->stream, dev->ipc_config.frame_fmt); /* calculate period size based on config */ cd->period_bytes = dev->frames * @@ -687,7 +688,7 @@ static int tone_prepare(struct comp_dev *dev) sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); - cd->channels = sourceb->stream.channels; + cd->channels = audio_stream_get_channels(&sourceb->stream); comp_info(dev, "tone_prepare(), cd->channels = %u, cd->rate = %u", cd->channels, cd->rate); diff --git a/src/drivers/amd/rembrandt/ipc.c b/src/drivers/amd/rembrandt/ipc.c index 58b3a88e6994..99097359dd3d 100644 --- a/src/drivers/amd/rembrandt/ipc.c +++ b/src/drivers/amd/rembrandt/ipc.c @@ -210,6 +210,11 @@ int ipc_platform_send_msg(const struct ipc_msg *msg) return ret; } +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* TODO: add support */ +} + int platform_ipc_init(struct ipc *ipc) { ipc_set_drvdata(ipc, NULL); diff --git a/src/drivers/amd/renoir/ipc.c b/src/drivers/amd/renoir/ipc.c index 52c93970945f..a5a89cd5b92b 100644 --- a/src/drivers/amd/renoir/ipc.c +++ b/src/drivers/amd/renoir/ipc.c @@ -226,6 +226,11 @@ int ipc_platform_send_msg(const struct ipc_msg *msg) return 0; } +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* TODO: add support */ +} + int platform_ipc_init(struct ipc *ipc) { ipc_set_drvdata(ipc, NULL); diff --git a/src/drivers/imx/edma.c b/src/drivers/imx/edma.c index 93567bb3cf0d..f521877857e2 100644 --- a/src/drivers/imx/edma.c +++ b/src/drivers/imx/edma.c @@ -285,7 +285,7 @@ static int edma_setup_tcd(struct dma_chan_data *channel, int16_t soff, int dest_width, uint32_t burst_elems) { int rc; -#ifdef CONFIG_IMX8ULP +#if defined(CONFIG_IMX8ULP) || defined(CONFIG_IMX93_A55) struct dai_data *dd = channel->dev_data; int direction, handshake, dmamux_cfg; #endif @@ -335,7 +335,7 @@ static int edma_setup_tcd(struct dma_chan_data *channel, int16_t soff, if (rc < 0) return rc; -#ifdef CONFIG_IMX8ULP +#if defined(CONFIG_IMX8ULP) || defined(CONFIG_IMX93_A55) /* Do not write EDMA_CH_MUX register when it has value, * otherwise the register will be cleared. */ diff --git a/src/drivers/imx/interrupt-generic.c b/src/drivers/imx/interrupt-generic.c index 32e03cebf816..19b58922cf6d 100644 --- a/src/drivers/imx/interrupt-generic.c +++ b/src/drivers/imx/interrupt-generic.c @@ -36,6 +36,7 @@ int irqstr_get_sof_int(int irqstr_int) void platform_interrupt_init(void) {} +#ifndef __ZEPHYR__ void platform_interrupt_set(uint32_t irq) { arch_interrupt_set(irq); @@ -45,6 +46,7 @@ void platform_interrupt_clear(uint32_t irq, uint32_t mask) { arch_interrupt_clear(irq); } +#endif /* __ZEPHYR__ */ uint32_t platform_interrupt_get_enabled(void) { diff --git a/src/drivers/imx/interrupt-irqsteer.c b/src/drivers/imx/interrupt-irqsteer.c index 3b5fda616ffb..2ef4f2f89e11 100644 --- a/src/drivers/imx/interrupt-irqsteer.c +++ b/src/drivers/imx/interrupt-irqsteer.c @@ -451,6 +451,7 @@ void platform_interrupt_init(void) interrupt_cascade_register(dsp_irq + i); } +#ifndef __ZEPHYR__ void platform_interrupt_set(uint32_t irq) { if (interrupt_is_dsp_direct(irq)) @@ -462,6 +463,7 @@ void platform_interrupt_clear(uint32_t irq, uint32_t mask) if (interrupt_is_dsp_direct(irq)) arch_interrupt_clear(irq); } +#endif /* __ZEPHYR */ uint32_t platform_interrupt_get_enabled(void) { diff --git a/src/drivers/imx/ipc.c b/src/drivers/imx/ipc.c index 56638185ee69..dd542ac03d6e 100644 --- a/src/drivers/imx/ipc.c +++ b/src/drivers/imx/ipc.c @@ -33,6 +33,16 @@ LOG_MODULE_REGISTER(ipc_task, CONFIG_SOF_LOG_LEVEL); +#ifdef CONFIG_ARM64 +/* thanks to the fact that ARM's GIC is supported + * by Zephyr there's no need to clear interrupts + * explicitly. This should already be done by Zephyr + * after executing the ISR. This macro is used for + * linkage purposes on ARM64-based platforms. + */ +#define interrupt_clear(irq) +#endif /* CONFIG_ARM64 */ + /* 389c9186-5a7d-4ad1-a02c-a02ecdadfb33 */ DECLARE_SOF_UUID("ipc-task", ipc_task_uuid, 0x389c9186, 0x5a7d, 0x4ad1, 0xa0, 0x2c, 0xa0, 0x2e, 0xcd, 0xad, 0xfb, 0x33); @@ -115,6 +125,7 @@ void ipc_platform_complete_cmd(struct ipc *ipc) // TODO: signal audio work to enter D3 in normal context /* are we about to enter D3 ? */ +#ifndef CONFIG_IMX93_A55 if (ipc->pm_prepare_D3) { while (1) /* @@ -124,6 +135,7 @@ void ipc_platform_complete_cmd(struct ipc *ipc) */ wait_for_interrupt(0); } +#endif /* CONFIG_IMX93_A55 */ } int ipc_platform_send_msg(const struct ipc_msg *msg) @@ -132,7 +144,8 @@ int ipc_platform_send_msg(const struct ipc_msg *msg) /* can't send notification when one is in progress */ if (ipc->is_notification_pending || - imx_mu_read(IMX_MU_xCR(IMX_MU_VERSION, IMX_MU_GCR)) & IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1)) { + imx_mu_read(IMX_MU_xCR(IMX_MU_VERSION, IMX_MU_GCR)) & + IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1)) { return -EBUSY; } @@ -148,6 +161,11 @@ int ipc_platform_send_msg(const struct ipc_msg *msg) return 0; } +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* TODO: add support */ +} + #if CONFIG_HOST_PTABLE struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) { @@ -223,8 +241,7 @@ int platform_ipc_init(struct ipc *ipc) * enable GP #0 for Host -> DSP message notification * enable GP #1 for DSP -> Host message confirmation */ - imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GIER, - IMX_MU_xCR_GIEn(IMX_MU_VERSION, 0) | + imx_mu_xcr_rmw(IMX_MU_VERSION, IMX_MU_GIER, IMX_MU_xCR_GIEn(IMX_MU_VERSION, 0) | IMX_MU_xCR_GIEn(IMX_MU_VERSION, 1), 0); return 0; @@ -306,7 +323,8 @@ int ipc_platform_poll_is_host_ready(void) int ipc_platform_poll_tx_host_msg(struct ipc_msg *msg) { /* can't send notification when one is in progress */ - if (imx_mu_read(IMX_MU_xCR(IMX_MU_VERSION, IMX_MU_GCR)) & IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1)) + if (imx_mu_read(IMX_MU_xCR(IMX_MU_VERSION, IMX_MU_GCR)) & + IMX_MU_xCR_GIRn(IMX_MU_VERSION, 1)) return 0; /* now send the message */ diff --git a/src/drivers/imx/sai.c b/src/drivers/imx/sai.c index 6ab240b49e95..303de4c7ea1a 100644 --- a/src/drivers/imx/sai.c +++ b/src/drivers/imx/sai.c @@ -345,8 +345,7 @@ static inline int sai_set_config(struct dai *dai, struct ipc_config_dai *common_ dai_update_bits(dai, REG_SAI_XCR4(REG_TX_DIR), mask_cr4, val_cr4); dai_update_bits(dai, REG_SAI_XCR5(REG_TX_DIR), mask_cr5, val_cr5); /* turn on (set to zero) stereo slot */ - dai_update_bits(dai, REG_SAI_XMR(REG_TX_DIR), REG_SAI_XMR_MASK, - twm); + dai_update_bits(dai, REG_SAI_XMR(REG_TX_DIR), REG_SAI_XMR_MASK, twm); val_cr2 |= REG_SAI_CR2_SYNC; mask_cr2 |= REG_SAI_CR2_SYNC_MASK; @@ -360,7 +359,7 @@ static inline int sai_set_config(struct dai *dai, struct ipc_config_dai *common_ dai_update_bits(dai, REG_SAI_XMR(REG_RX_DIR), REG_SAI_XMR_MASK, twm); -#ifdef CONFIG_IMX8M +#if defined(CONFIG_IMX8M) || defined(CONFIG_IMX93_A55) /* * For i.MX8MP, MCLK is bound with TX enable bit. * Therefore, enable transmitter to output MCLK diff --git a/src/drivers/imx/sdma.c b/src/drivers/imx/sdma.c index 2099c2ffe2b4..c66cbc5b8660 100644 --- a/src/drivers/imx/sdma.c +++ b/src/drivers/imx/sdma.c @@ -888,6 +888,8 @@ static int sdma_get_data_size(struct dma_chan_data *channel, uint32_t *avail, return -EINVAL; } + dcache_invalidate_region(pdata->desc, sizeof(pdata->desc[0]) * SDMA_MAX_BDS); + for (i = 0; i < pdata->desc_count && i < SDMA_MAX_BDS; i++) { if (pdata->desc[i].config & SDMA_BD_DONE) continue; /* These belong to SDMA controller */ diff --git a/src/drivers/intel/cavs/ipc.c b/src/drivers/intel/cavs/ipc.c index f5d6dace21db..26810730c601 100644 --- a/src/drivers/intel/cavs/ipc.c +++ b/src/drivers/intel/cavs/ipc.c @@ -196,6 +196,11 @@ int ipc_platform_send_msg(const struct ipc_msg *msg) return 0; } +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* TODO: add support */ +} + int platform_ipc_init(struct ipc *ipc) { int irq; diff --git a/src/drivers/intel/ssp/ssp.c b/src/drivers/intel/ssp/ssp.c index a00ff4c2b797..e654161181ed 100644 --- a/src/drivers/intel/ssp/ssp.c +++ b/src/drivers/intel/ssp/ssp.c @@ -74,9 +74,18 @@ static void ssp_empty_rx_fifo(struct dai *dai) uint64_t sample_ticks = clock_ticks_per_sample(PLATFORM_DEFAULT_CLOCK, ssp->params.fsync_rate); uint32_t retry = SSP_RX_FLUSH_RETRY_MAX; + bool direct_reads = ssp->state[DAI_DIR_CAPTURE] <= COMP_STATE_PREPARE; uint32_t entries; uint32_t i; +#if CONFIG_DMA_SUSPEND_DRAIN + /* + * In drain mode, DMA is stopped before DAI, so flush must be + * always done with direct register read. + */ + direct_reads = true; +#endif + /* * To make sure all the RX FIFO entries are read out for the flushing, * we need to wait a minimal SSP port delay after entries are all read, @@ -87,9 +96,12 @@ static void ssp_empty_rx_fifo(struct dai *dai) while ((ssp_read(dai, SSSR) & SSSR_RNE) && retry--) { entries = SSCR3_RFL_VAL(ssp_read(dai, SSCR3)); dai_dbg(dai, "ssp_empty_rx_fifo(), before flushing, entries %d", entries); - for (i = 0; i < entries + 1; i++) - /* read to try empty fifo */ - ssp_read(dai, SSDR); + + /* let DMA consume data or read RX FIFO directly */ + if (direct_reads) { + for (i = 0; i < entries + 1; i++) + ssp_read(dai, SSDR); + } /* wait to get valid fifo status and re-check */ wait_delay(sample_ticks); @@ -963,6 +975,10 @@ static void ssp_early_start(struct dai *dai, int direction) key = k_spin_lock(&dai->lock); + /* RX fifo must be cleared before start */ + if (direction == DAI_DIR_CAPTURE) + ssp_empty_rx_fifo(dai); + /* request mclk/bclk */ ssp_pre_start(dai); diff --git a/src/drivers/mediatek/mt818x/ipc.c b/src/drivers/mediatek/mt818x/ipc.c index b7493ce0ddfe..b074c21f8413 100644 --- a/src/drivers/mediatek/mt818x/ipc.c +++ b/src/drivers/mediatek/mt818x/ipc.c @@ -107,6 +107,11 @@ int ipc_platform_send_msg(const struct ipc_msg *msg) return 0; } +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* TODO: add support */ +} + #if CONFIG_HOST_PTABLE struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) { diff --git a/src/drivers/mediatek/mt8195/ipc.c b/src/drivers/mediatek/mt8195/ipc.c index 676f6b45b55a..1fff0ff66566 100644 --- a/src/drivers/mediatek/mt8195/ipc.c +++ b/src/drivers/mediatek/mt8195/ipc.c @@ -108,6 +108,11 @@ int ipc_platform_send_msg(const struct ipc_msg *msg) return 0; } +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* TODO: add support */ +} + #if CONFIG_HOST_PTABLE struct ipc_data_host_buffer *ipc_platform_get_host_buffer(struct ipc *ipc) { diff --git a/src/include/ipc4/alh.h b/src/include/ipc4/alh.h index a5a15b19be48..af30a2a36723 100644 --- a/src/include/ipc4/alh.h +++ b/src/include/ipc4/alh.h @@ -25,10 +25,15 @@ #define __SOF_IPC4_ALH_H__ #include +#include #include #define IPC4_ALH_MAX_NUMBER_OF_GTW 16 +#ifdef CONFIG_DMA_INTEL_ADSP_GPDMA #define IPC4_ALH_DAI_INDEX_OFFSET 7 +#else +#define IPC4_ALH_DAI_INDEX_OFFSET 0 +#endif /* copier id = (group id << 4) + codec id + IPC4_ALH_DAI_INDEX_OFFSET * dai_index = (group id << 8) + codec id; diff --git a/src/include/ipc4/ams_helpers.h b/src/include/ipc4/ams_helpers.h new file mode 100644 index 000000000000..35c9557a733b --- /dev/null +++ b/src/include/ipc4/ams_helpers.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2023 Intel Corporation + * + * Author: Ievgen Ganakov + */ + +#ifndef __SOF_LIB_AMS_HELPERS_H__ +#define __SOF_LIB_AMS_HELPERS_H__ + +#include +#include +#include + +#if CONFIG_AMS + +int ams_helper_register_producer(const struct comp_dev *dev, + uint32_t *ams_uuid_id, + const uint8_t *msg_uuid); + +int ams_helper_unregister_producer(const struct comp_dev *dev, + uint32_t ams_uuid_id); + +int ams_helper_register_consumer(struct comp_dev *dev, + uint32_t *ams_uuid_id, + const uint8_t *msg_uuid, + ams_msg_callback_fn callback); + +int ams_helper_unregister_consumer(struct comp_dev *dev, + uint32_t ams_uuid_id, + ams_msg_callback_fn callback); + +void ams_helper_prepare_payload(const struct comp_dev *dev, + struct ams_message_payload *payload, + uint32_t ams_uuid_id, + uint8_t *message, + size_t message_size); + +#endif /* CONFIG_AMS */ + +#endif /* __SOF_LIB_AMS_HELPERS_H__ */ diff --git a/src/include/ipc4/copier.h b/src/include/ipc4/copier.h index 02c467cd1cfd..5d1ae17d3428 100644 --- a/src/include/ipc4/copier.h +++ b/src/include/ipc4/copier.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -226,12 +227,6 @@ struct ipc4_data_segment_enabled { uint32_t data_seg_size; } __attribute__((packed, aligned(4))); -/* One of copy_single_channel_cXX() to mux/demux channels into/from copier multi_endpoint_buffer */ -typedef void (* channel_copy_func)(struct audio_stream __sparse_cache *dst, - int dst_channel, - const struct audio_stream __sparse_cache *src, - int src_channel, int frame_count); - struct copier_data { /* * struct ipc4_copier_module_cfg actually has variable size, but we @@ -245,7 +240,6 @@ struct copier_data { /* buffer to mux/demux data from/to multiple endpoint buffers for ALH multi-gateway case */ struct comp_buffer *multi_endpoint_buffer; - channel_copy_func copy_single_channel; bool bsource_buffer; @@ -263,9 +257,30 @@ struct copier_data { uint64_t output_total_data_processed; struct host_data *hd; bool ipc_gtw; + struct dai_data *dd[IPC4_ALH_MAX_NUMBER_OF_GTW]; + uint32_t channels[IPC4_ALH_MAX_NUMBER_OF_GTW]; + uint32_t chan_map[IPC4_ALH_MAX_NUMBER_OF_GTW]; + struct ipcgtw_data *ipcgtw_data; }; int apply_attenuation(struct comp_dev *dev, struct copier_data *cd, struct comp_buffer __sparse_cache *sink, int frame); +pcm_converter_func get_converter_func(const struct ipc4_audio_format *in_fmt, + const struct ipc4_audio_format *out_fmt, + enum ipc4_gateway_type type, + enum ipc4_direction_type dir); + +struct comp_ipc_config; +int create_endpoint_buffer(struct comp_dev *parent_dev, + struct copier_data *cd, + struct comp_ipc_config *config, + const struct ipc4_copier_module_cfg *copier_cfg, + enum ipc4_gateway_type type, + bool create_multi_endpoint_buffer, + int index); + +enum sof_ipc_stream_direction + get_gateway_direction(enum ipc4_connector_node_id_type node_id_type); + #endif diff --git a/src/include/ipc4/ipcgtw.h b/src/include/ipc4/ipcgtw.h deleted file mode 100644 index 8e97cd08e1ca..000000000000 --- a/src/include/ipc4/ipcgtw.h +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright 2023 Intel Corporation. All rights reserved. - */ - -#ifndef __SOF_IPC4_IPCGTW_H__ -#define __SOF_IPC4_IPCGTW_H__ - -/**< IPC header format for IPC gateway messages */ -struct ipc4_ipcgtw_cmd { - union { - uint32_t dat; - - struct { - /**< Command, see below */ - uint32_t cmd : 24; - - /**< One of Global::Type */ - uint32_t type : 5; - - /**< Msg::MSG_REQUEST */ - uint32_t rsp : 1; - - /**< Msg::FW_GEN_MSG */ - uint32_t msg_tgt : 1; - - uint32_t _reserved_0 : 1; - } r; - } primary; - union { - uint32_t dat; - struct { - uint32_t data_size : 30; - uint32_t _reserved_0 : 2; - } r; - } extension; -} __packed __aligned(4); - -/**< Values of ipc4_ipcgtw_cmd::primary.r.cmd */ -enum { - IPC4_IPCGWCMD_GET_DATA = 1, - IPC4_IPCGWCMD_SET_DATA = 2, - IPC4_IPCGWCMD_FLUSH_DATA = 3 -}; - -/* Incoming IPC gateway message */ -struct ipc4_ipc_gateway_cmd_data { - /* node_id of the target gateway */ - union ipc4_connector_node_id node_id; - /* Payload (actual size is in the header extension.r.data_size) */ - uint8_t payload[]; -}; - -/* Reply to IPC gateway message */ -struct ipc4_ipc_gateway_cmd_data_reply { - union { - uint32_t size_avail; /* Reply for IPC4_IPCGWCMD_GET_DATA */ - uint32_t size_consumed; /* Reply for IPC4_IPCGWCMD_SET_DATA */ - } u; - /* Total reply size is returned in reply header extension.r.data_size. - * This payload size if 4 bytes smaller (size of the union above). - */ - uint8_t payload[]; -}; - -int ipcgtw_process_cmd(const struct ipc4_ipcgtw_cmd *cmd, - void *reply_payload, uint32_t *reply_payload_size); - -#endif /* __SOF_IPC4_IPCGTW_H__ */ diff --git a/src/include/ipc4/notification.h b/src/include/ipc4/notification.h index d4bfeaf3826c..658cbcc50ce1 100644 --- a/src/include/ipc4/notification.h +++ b/src/include/ipc4/notification.h @@ -25,6 +25,7 @@ #include #include +#include /* ipc4 notification msg */ enum sof_ipc4_notification_type { diff --git a/src/include/sof/audio/audio_stream.h b/src/include/sof/audio/audio_stream.h index 4665903bba75..9a17cb229020 100644 --- a/src/include/sof/audio/audio_stream.h +++ b/src/include/sof/audio/audio_stream.h @@ -77,6 +77,130 @@ struct audio_stream { bool underrun_permitted; /**< indicates whether underrun is permitted */ }; +static inline void *audio_stream_get_rptr(const struct audio_stream __sparse_cache *buf) +{ + return buf->r_ptr; +} + +static inline void *audio_stream_get_wptr(const struct audio_stream __sparse_cache *buf) +{ + return buf->w_ptr; +} + +static inline void *audio_stream_get_end_addr(const struct audio_stream __sparse_cache *buf) +{ + return buf->end_addr; +} + +static inline void *audio_stream_get_addr(const struct audio_stream __sparse_cache *buf) +{ + return buf->addr; +} + +static inline uint32_t audio_stream_get_size(const struct audio_stream __sparse_cache *buf) +{ + return buf->size; +} + +static inline uint32_t audio_stream_get_avail(const struct audio_stream __sparse_cache *buf) +{ + return buf->avail; +} + +static inline uint32_t audio_stream_get_free(const struct audio_stream __sparse_cache *buf) +{ + return buf->free; +} + +static inline enum sof_ipc_frame audio_stream_get_frm_fmt( + const struct audio_stream __sparse_cache *buf) +{ + return buf->frame_fmt; +} + +static inline enum sof_ipc_frame audio_stream_get_valid_fmt( + const struct audio_stream __sparse_cache *buf) +{ + return buf->valid_sample_fmt; +} + +static inline uint32_t audio_stream_get_rate(const struct audio_stream __sparse_cache *buf) +{ + return buf->rate; +} + +static inline uint32_t audio_stream_get_channels(const struct audio_stream __sparse_cache *buf) +{ + return buf->channels; +} + +static inline bool audio_stream_get_underrun(const struct audio_stream __sparse_cache *buf) +{ + return buf->underrun_permitted; +} + +static inline bool audio_stream_get_overrun(const struct audio_stream __sparse_cache *buf) +{ + return buf->overrun_permitted; +} + +static inline void audio_stream_set_rptr(struct audio_stream __sparse_cache *buf, void *val) +{ + buf->r_ptr = val; +} + +static inline void audio_stream_set_wptr(struct audio_stream __sparse_cache *buf, void *val) +{ + buf->w_ptr = val; +} + +static inline void audio_stream_set_end_addr(struct audio_stream __sparse_cache *buf, void *val) +{ + buf->end_addr = val; +} + +static inline void audio_stream_set_addr(struct audio_stream __sparse_cache *buf, void *val) +{ + buf->addr = val; +} + +static inline void audio_stream_set_size(struct audio_stream __sparse_cache *buf, uint32_t val) +{ + buf->size = val; +} + +static inline void audio_stream_set_avail(struct audio_stream __sparse_cache *buf, uint32_t val) +{ + buf->avail = val; +} + +static inline void audio_stream_set_free(struct audio_stream __sparse_cache *buf, uint32_t val) +{ + buf->free = val; +} + +static inline void audio_stream_set_frm_fmt(struct audio_stream __sparse_cache *buf, + enum sof_ipc_frame val) +{ + buf->frame_fmt = val; +} + +static inline void audio_stream_set_valid_fmt(struct audio_stream __sparse_cache *buf, + enum sof_ipc_frame val) +{ + buf->valid_sample_fmt = val; +} + +static inline void audio_stream_set_rate(struct audio_stream __sparse_cache *buf, uint32_t val) +{ + buf->rate = val; +} + +static inline void audio_stream_set_channels(struct audio_stream __sparse_cache *buf, uint16_t val) +{ + buf->channels = val; +} + /** * Retrieves readable address of a sample at specified index (see versions of * this macro specialized for various sample types). @@ -561,6 +685,12 @@ static inline void audio_stream_init(struct audio_stream __sparse_cache *buffer, buffer->size = size; buffer->addr = buff_addr; buffer->end_addr = (char *)buffer->addr + size; + + /* set the default alignment info. + * set byte_align as 1 means no alignment limit on byte. + * set frame_align as 1 means no alignment limit on frame. + */ + audio_stream_init_alignment_constants(1, 1, buffer); audio_stream_reset(buffer); } @@ -778,8 +908,8 @@ static inline int audio_stream_set_zero(struct audio_stream __sparse_cache *buff static inline void audio_stream_fmt_conversion(enum ipc4_bit_depth depth, enum ipc4_bit_depth valid, - enum sof_ipc_frame __sparse_cache *frame_fmt, - enum sof_ipc_frame __sparse_cache *valid_fmt, + enum sof_ipc_frame *frame_fmt, + enum sof_ipc_frame *valid_fmt, enum ipc4_sample_type type) { /* IPC4_DEPTH_16BIT (16) <---> SOF_IPC_FRAME_S16_LE (0) diff --git a/src/include/sof/audio/buffer.h b/src/include/sof/audio/buffer.h index cada0049e182..c0fdc213d5d7 100644 --- a/src/include/sof/audio/buffer.h +++ b/src/include/sof/audio/buffer.h @@ -189,9 +189,9 @@ struct buffer_cb_free { } while (0) /* pipeline buffer creation and destruction */ -struct comp_buffer *buffer_alloc(uint32_t size, uint32_t caps, uint32_t align); +struct comp_buffer *buffer_alloc(uint32_t size, uint32_t caps, uint32_t flags, uint32_t align); struct comp_buffer *buffer_new(const struct sof_ipc_buffer *desc); -int buffer_set_size(struct comp_buffer __sparse_cache *buffer, uint32_t size); +int buffer_set_size(struct comp_buffer __sparse_cache *buffer, uint32_t size, uint32_t alignment); void buffer_free(struct comp_buffer *buffer); void buffer_zero(struct comp_buffer __sparse_cache *buffer); diff --git a/src/include/sof/audio/component.h b/src/include/sof/audio/component.h index 5a06857b188e..4c3145b21712 100644 --- a/src/include/sof/audio/component.h +++ b/src/include/sof/audio/component.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -41,6 +42,7 @@ #include #include #include +#include struct comp_dev; struct sof_ipc_stream_posn; @@ -347,8 +349,8 @@ struct comp_ops { * * Mandatory for components that allocate DAI. */ - int (*dai_config)(struct comp_dev *dev, struct ipc_config_dai *dai_config, - const void *dai_spec_config); + int (*dai_config)(struct dai_data *dd, struct comp_dev *dev, + struct ipc_config_dai *dai_config, const void *dai_spec_config); /** * Used to pass standard and bespoke commands (with optional data). @@ -708,13 +710,10 @@ void sys_comp_crossover_init(void); void sys_comp_dai_init(void); void sys_comp_dcblock_init(void); void sys_comp_drc_init(void); -void sys_comp_eq_iir_init(void); void sys_comp_host_init(void); void sys_comp_kpb_init(void); -void sys_comp_mixer_init(void); void sys_comp_multiband_drc_init(void); void sys_comp_selector_init(void); -void sys_comp_src_init(void); void sys_comp_module_demux_interface_init(void); void sys_comp_module_eq_fir_interface_init(void); @@ -722,6 +721,7 @@ void sys_comp_module_eq_iir_interface_init(void); void sys_comp_module_mfcc_interface_init(void); void sys_comp_module_mixer_interface_init(void); void sys_comp_module_mux_interface_init(void); +void sys_comp_module_src_interface_init(void); void sys_comp_module_tdfb_interface_init(void); void sys_comp_module_volume_interface_init(void); @@ -781,6 +781,8 @@ int comp_set_state(struct comp_dev *dev, int cmd); static inline void component_set_nearest_period_frames(struct comp_dev *current, uint32_t rate) { + uint64_t frames; + /* Sample rate is in Hz and period in microseconds. * As we don't have floats use scale divider 1000000. * Also integer round up the result. @@ -788,20 +790,25 @@ static inline void component_set_nearest_period_frames(struct comp_dev *current, * compatible with current 45K adjustment. 48K is a suitable * adjustment. */ + switch (rate) { case 44100: - current->frames = 48000 * current->period / 1000000; + rate = 48000; break; case 88200: - current->frames = 96000 * current->period / 1000000; + rate = 96000; break; case 176400: - current->frames = 192000 * current->period / 1000000; + rate = 192000; break; default: - current->frames = ceil_divide(rate * current->period, 1000000); break; } + + frames = SOF_DIV_ROUND_UP((uint64_t)rate * current->period, 1000000); + + assert(frames <= UINT_MAX); + current->frames = (uint32_t)frames; } /** \name XRUN handling. diff --git a/src/include/sof/audio/component_ext.h b/src/include/sof/audio/component_ext.h index 339b479b3ff2..efa8e1b7767b 100644 --- a/src/include/sof/audio/component_ext.h +++ b/src/include/sof/audio/component_ext.h @@ -252,16 +252,27 @@ static inline int comp_reset(struct comp_dev *dev) return 0; } +#if CONFIG_IPC_MAJOR_3 /** See comp_ops::dai_config */ static inline int comp_dai_config(struct comp_dev *dev, struct ipc_config_dai *config, const void *spec_config) { + struct dai_data *dd = comp_get_drvdata(dev); + if (dev->drv->ops.dai_config) - return dev->drv->ops.dai_config(dev, config, spec_config); + return dev->drv->ops.dai_config(dd, dev, config, spec_config); return 0; } - +#elif CONFIG_IPC_MAJOR_4 +static inline int comp_dai_config(struct dai_data *dd, struct comp_dev *dev, + struct ipc_config_dai *config, const void *spec_config) +{ + return dai_config(dd, dev, config, spec_config); +} +#else +#error Unknown IPC major version +#endif /** See comp_ops::position */ static inline int comp_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) @@ -351,26 +362,6 @@ static inline int comp_get_endpoint_type(struct comp_dev *dev) } } -#if CONFIG_IPC_MAJOR_4 -#include -static inline struct comp_dev *comp_get_dai(struct comp_dev *parent, int index) -{ - struct copier_data *cd = comp_get_drvdata(parent); - - if (index >= ARRAY_SIZE(cd->endpoint)) - return NULL; - - return cd->endpoint[index]; -} -#elif CONFIG_IPC_MAJOR_3 -static inline struct comp_dev *comp_get_dai(struct comp_dev *parent, int index) -{ - return parent; -} -#else -#error Unknown IPC major version -#endif - /** * Called to check whether component schedules its pipeline. * @param dev Component device. diff --git a/src/include/sof/audio/dai_copier.h b/src/include/sof/audio/dai_copier.h new file mode 100644 index 000000000000..5e28a9500e36 --- /dev/null +++ b/src/include/sof/audio/dai_copier.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Baofeng Tian + */ + +/** + * \file audio/dai_copier.h + * \brief dai copier shared header file + * \authors Baofeng Tian + */ + +#ifndef __SOF_LIB_DAI_COPIER_H__ +#define __SOF_LIB_DAI_COPIER_H__ + +struct ipc_config_dai; +struct comp_dev; +struct dai_data; +int dai_zephyr_new(struct dai_data *dd, struct comp_dev *dev, + const struct ipc_config_dai *dai_cfg); + +void dai_zephyr_free(struct dai_data *dd); + +int dai_zephyr_config_prepare(struct dai_data *dd, struct comp_dev *dev); + +int dai_zephyr_prepare(struct dai_data *dd, struct comp_dev *dev); + +void dai_zephyr_reset(struct dai_data *dd, struct comp_dev *dev); + +int dai_zephyr_trigger(struct dai_data *dd, struct comp_dev *dev, int cmd); + +int dai_zephyr_position(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_posn *posn); + +int dai_zephyr_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params); + +int dai_zephyr_copy(struct dai_data *dd, struct comp_dev *dev, pcm_converter_func *converter); + +int dai_zephyr_ts_config_op(struct dai_data *dd, struct comp_dev *dev); + +int dai_zephyr_ts_start(struct dai_data *dd, struct comp_dev *dev); + +int dai_zephyr_ts_stop(struct dai_data *dd, struct comp_dev *dev); + +int dai_zephyr_ts_get(struct dai_data *dd, struct comp_dev *dev, struct timestamp_data *tsd); + +int dai_zephyr_get_hw_params(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_params *params, int dir); + +int dai_zephyr_multi_endpoint_copy(struct dai_data **dd, struct comp_dev *dev, + struct comp_buffer *multi_endpoint_buffer, + int num_endpoints); + +int dai_zephyr_unbind(struct dai_data *dd, struct comp_dev *dev, void *data); + +#endif /* __SOF_LIB_DAI_COPIER_H__ */ diff --git a/src/include/sof/audio/host_copier.h b/src/include/sof/audio/host_copier.h index eac9a2c7c0a1..b4857af80595 100644 --- a/src/include/sof/audio/host_copier.h +++ b/src/include/sof/audio/host_copier.h @@ -21,9 +21,11 @@ #include #include +typedef void (*copy_callback_t)(struct comp_dev *dev, size_t bytes); + struct host_data; /** \brief Host copy function interface. */ -typedef int (*host_copy_func)(struct host_data *hd, struct comp_dev *dev); +typedef int (*host_copy_func)(struct host_data *hd, struct comp_dev *dev, copy_callback_t cb); /** * \brief Host buffer info. @@ -51,6 +53,8 @@ struct host_data { #ifdef __ZEPHYR__ struct dma_config z_config; #endif + struct comp_dev *cb_dev; + struct comp_buffer *dma_buffer; struct comp_buffer *local_buffer; @@ -93,63 +97,16 @@ struct host_data { struct ipc_msg *msg; /**< host notification */ }; -#if CONFIG_ZEPHYR_NATIVE_DRIVERS int host_zephyr_new(struct host_data *hd, struct comp_dev *dev, const struct ipc_config_host *ipc_host, uint32_t config_id); - void host_zephyr_free(struct host_data *hd); - int host_zephyr_prepare(struct host_data *hd); - void host_zephyr_reset(struct host_data *hd, uint16_t state); - int host_zephyr_trigger(struct host_data *hd, struct comp_dev *dev, int cmd); - int host_zephyr_params(struct host_data *hd, struct comp_dev *dev, - struct sof_ipc_stream_params *params); - -int host_zephyr_copy(struct host_data *hd, struct comp_dev *dev); - + struct sof_ipc_stream_params *params, notifier_callback_t cb); +int host_zephyr_copy(struct host_data *hd, struct comp_dev *dev, copy_callback_t cb); void host_update_position(struct host_data *hd, struct comp_dev *dev, uint32_t bytes); - void host_one_shot_cb(struct host_data *hd, uint32_t bytes); -#else -static inline int host_zephyr_new(struct host_data *hd, struct comp_dev *dev, - const struct ipc_config_host *ipc_host, uint32_t config_id) -{ - return 0; -} -static inline void host_zephyr_free(struct host_data *hd) {} - -static inline int host_zephyr_prepare(struct host_data *hd) -{ - return 0; -} - -static inline void host_zephyr_reset(struct host_data *hd, uint16_t state) {} - -static inline int host_zephyr_trigger(struct host_data *hd, struct comp_dev *dev, - int cmd) -{ - return 0; -} - -static inline int host_zephyr_params(struct host_data *hd, struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - return 0; -} - -static inline int host_zephyr_copy(struct host_data *hd, struct comp_dev *dev) -{ - return 0; -} - -static inline void host_update_position(struct host_data *hd, - struct comp_dev *dev, uint32_t bytes) {} - -static inline void host_one_shot_cb(struct host_data *hd, uint32_t bytes) {} - -#endif #endif /* __SOF_HOST_COPIER_H__ */ diff --git a/src/include/sof/audio/ipc-config.h b/src/include/sof/audio/ipc-config.h index eb25e22b4782..8bedb7002e0c 100644 --- a/src/include/sof/audio/ipc-config.h +++ b/src/include/sof/audio/ipc-config.h @@ -9,6 +9,42 @@ #include #include +/* ACE 2.0 and newer */ +#define GTW_DMA_CONFIG_ID 0x1000 +#define GTW_DMA_INVALID_CHANNEL_ID 0xffffffff +/* Maximum number of devices */ +#define GTW_DMA_DEVICE_MAX_COUNT 16 + +struct dma_device_stream_channel_map { + uint32_t device_address; + uint32_t channel_map; +}; + +struct dma_stream_channel_map { + uint32_t device_count; + struct dma_device_stream_channel_map map[GTW_DMA_DEVICE_MAX_COUNT]; +}; + +struct ipc_dma_config { + uint8_t dma_method; /**< DMA method */ + uint8_t pre_allocated_by_host; /**< 1 - DMA pre-allocated by host, otherwise to be + * allocated by DSP + */ + uint16_t rsvd; + uint32_t dma_channel_id; /**< channel ID if DMA pre-allocated by host, otherwise + * invalid channel ID + */ + uint32_t stream_id; + /* DmaStreamChannelMap */ + struct dma_stream_channel_map channel_map; + uint32_t dma_priv_config_size; + uint8_t dma_priv_config[0]; +} __attribute__((packed, aligned(4))); + +#define GET_IPC_DMA_CONFIG(buffer, size) \ + ((struct ipc_dma_config *)((uint8_t *)(buffer) + (size) - sizeof(struct ipc_dma_config))) +#define GET_IPC_DMA_CONFIG_ID(buffer, size) ((uint32_t *)GET_IPC_DMA_CONFIG(buffer, size) - 2) + /* * Generic IPC information for base components. Fields can be added here with NO impact on * IPC ABI version. @@ -39,6 +75,10 @@ struct ipc_config_dai { uint32_t feature_mask; /**< copier feature mask (set directly from * ipc4_copier_module_cfg on init) */ + struct ipc_dma_config *host_dma_config; /**< DMA config - required for ACE 2.0 and newer */ + const struct ipc4_audio_format *out_fmt;/**< audio format for output pin 0 - required + * for ACE 2.0 and newer + */ }; /* generic volume component */ diff --git a/src/include/sof/audio/ipcgtw_copier.h b/src/include/sof/audio/ipcgtw_copier.h new file mode 100644 index 000000000000..b50600a646d1 --- /dev/null +++ b/src/include/sof/audio/ipcgtw_copier.h @@ -0,0 +1,108 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Baofeng Tian + */ + +/** + * \file audio/ipcgtw_copier.h + * \brief ipcgtw copier shared header file + * \authors Baofeng Tian + */ + +#ifndef __SOF_IPCGTW_COPIER_H__ +#define __SOF_IPCGTW_COPIER_H__ + +#include +#include +#include +#include +#include + +/* Host communicates with IPC gateways via global IPC messages. To address a particular + * IPC gateway, its node_id is sent in message payload. Hence we need to keep a list of existing + * IPC gateways and their node_ids to search for a gateway host wants to address. + */ +struct ipcgtw_data { + union ipc4_connector_node_id node_id; + struct comp_dev *dev; + struct list_item item; + + /* IPC gateway buffer size comes in blob at creation time, we keep size here + * to resize buffer later at ipcgtw_params(). + */ + uint32_t buf_size; +}; + +/**< IPC header format for IPC gateway messages */ +struct ipc4_ipcgtw_cmd { + union { + uint32_t dat; + + struct { + /**< Command, see below */ + uint32_t cmd : 24; + + /**< One of Global::Type */ + uint32_t type : 5; + + /**< Msg::MSG_REQUEST */ + uint32_t rsp : 1; + + /**< Msg::FW_GEN_MSG */ + uint32_t msg_tgt : 1; + + uint32_t _reserved_0 : 1; + } r; + } primary; + union { + uint32_t dat; + struct { + uint32_t data_size : 30; + uint32_t _reserved_0 : 2; + } r; + } extension; +} __packed __aligned(4); + +/**< Values of ipc4_ipcgtw_cmd::primary.r.cmd */ +enum { + IPC4_IPCGWCMD_GET_DATA = 1, + IPC4_IPCGWCMD_SET_DATA = 2, + IPC4_IPCGWCMD_FLUSH_DATA = 3 +}; + +/* Incoming IPC gateway message */ +struct ipc4_ipc_gateway_cmd_data { + /* node_id of the target gateway */ + union ipc4_connector_node_id node_id; + /* Payload (actual size is in the header extension.r.data_size) */ + uint8_t payload[]; +} __packed __aligned(4); + +/* Reply to IPC gateway message */ +struct ipc4_ipc_gateway_cmd_data_reply { + union { + uint32_t size_avail; /* Reply for IPC4_IPCGWCMD_GET_DATA */ + uint32_t size_consumed; /* Reply for IPC4_IPCGWCMD_SET_DATA */ + } u; + /* Total reply size is returned in reply header extension.r.data_size. + * This payload size if 4 bytes smaller (size of the union above). + */ + uint8_t payload[]; +} __packed __aligned(4); + +int copier_ipcgtw_process(const struct ipc4_ipcgtw_cmd *cmd, + void *reply_payload, uint32_t *reply_payload_size); + +int copier_ipcgtw_params(struct ipcgtw_data *ipcgtw_data, struct comp_dev *dev, + struct sof_ipc_stream_params *params); + +void copier_ipcgtw_reset(struct comp_dev *dev); + +int copier_ipcgtw_create(struct comp_dev *parent_dev, struct copier_data *cd, + struct comp_ipc_config *config, + const struct ipc4_copier_module_cfg *copier); + +void copier_ipcgtw_free(struct copier_data *cd); +#endif /* __SOF_IPCGTW_COPIER_H__ */ diff --git a/src/include/sof/audio/mixer.h b/src/include/sof/audio/mixer.h index 8c4aeab7f189..c5836ca89537 100644 --- a/src/include/sof/audio/mixer.h +++ b/src/include/sof/audio/mixer.h @@ -68,7 +68,7 @@ static inline mixer_func mixer_get_processing_function(struct comp_dev *dev, /* map the volume function for source and sink buffers */ for (i = 0; i < mixer_func_count; i++) { - if (sinkb->stream.frame_fmt != mixer_func_map[i].frame_fmt) + if (audio_stream_get_frm_fmt(&sinkb->stream) != mixer_func_map[i].frame_fmt) continue; return mixer_func_map[i].func; diff --git a/src/include/sof/audio/module_adapter/module/generic.h b/src/include/sof/audio/module_adapter/module/generic.h index a12e7f857f4e..f0bc0a4c539c 100644 --- a/src/include/sof/audio/module_adapter/module/generic.h +++ b/src/include/sof/audio/module_adapter/module/generic.h @@ -59,6 +59,7 @@ static const struct comp_driver comp_##adapter##_module = { \ .get_attribute = module_adapter_get_attribute,\ .bind = module_adapter_bind,\ .unbind = module_adapter_unbind,\ + .get_total_data_processed = module_adapter_get_total_data_processed,\ }, \ }; \ \ @@ -209,6 +210,10 @@ struct processing_module { /* table containing the list of connected sources */ struct module_source_info *source_info; + + /* total processed data after stream started */ + uint64_t total_data_consumed; + uint64_t total_data_produced; }; /*****************************************************************************/ @@ -248,6 +253,8 @@ int module_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_ int module_adapter_get_attribute(struct comp_dev *dev, uint32_t type, void *value); int module_adapter_bind(struct comp_dev *dev, void *data); int module_adapter_unbind(struct comp_dev *dev, void *data); +uint64_t module_adapter_get_total_data_processed(struct comp_dev *dev, + uint32_t stream_no, bool input); static inline void module_update_buffer_position(struct input_stream_buffer *input_buffers, struct output_stream_buffer *output_buffers, diff --git a/src/include/sof/audio/volume.h b/src/include/sof/audio/volume.h index e72407a13fd4..0b35ee8dbf57 100644 --- a/src/include/sof/audio/volume.h +++ b/src/include/sof/audio/volume.h @@ -65,8 +65,10 @@ struct sof_ipc_ctrl_value_chan; //** \brief Volume gain Qx.y */ #define COMP_VOLUME_Q1_23 1 -//** \brief Volume gain Qx.y integer x number of bits including sign bit. */ -#define VOL_QXY_X 1 +/** \brief Volume gain Qx.y integer x number of bits including sign bit. + * With Q8.23 format the gain range is -138.47 to +42.14 dB. + */ +#define VOL_QXY_X 8 //** \brief Volume gain Qx.y fractional y number of bits. */ #define VOL_QXY_Y 23 @@ -190,7 +192,7 @@ static inline vol_scale_func vol_get_processing_function(struct comp_dev *dev, /* map the volume function for source and sink buffers */ for (i = 0; i < volume_func_count; i++) { - if (sinkb->stream.frame_fmt != volume_func_map[i].frame_fmt) + if (audio_stream_get_frm_fmt(&sinkb->stream) != volume_func_map[i].frame_fmt) continue; return volume_func_map[i].func; diff --git a/src/include/sof/common.h b/src/include/sof/common.h index b23463dc57ec..6a875f5a90f7 100644 --- a/src/include/sof/common.h +++ b/src/include/sof/common.h @@ -43,7 +43,7 @@ (compile_check(is_power_of_2(alignment)) ? \ ALIGN_UP_INTERNAL(size, alignment) : 0xBADCAFE) -#ifdef __XCC__ +#if defined(__XCC__) || defined(__clang__) /* * xcc doesn't support __builtin_constant_p() so we can only do run-time @@ -62,7 +62,7 @@ (size) & ~((alignment) - 1); \ }) -#else /* not __XCC__ */ +#else /* not __XCC__ or __clang__ */ /* If we can't tell at compile time, assume it's OK and defer to run-time */ #define COMPILE_TIME_ALIGNED(align) (!__builtin_constant_p(align) || \ @@ -82,7 +82,7 @@ (size) & ~((alignment) - 1); \ }) -#endif /* not __XCC__ */ +#endif /* not __XCC__ or __clang__ */ #else /* not VERIFY_ALIGN */ diff --git a/src/include/sof/debug/gdb/gdb.h b/src/include/sof/debug/gdb/gdb.h index ac6abfb9a4a3..c27e60e64290 100644 --- a/src/include/sof/debug/gdb/gdb.h +++ b/src/include/sof/debug/gdb/gdb.h @@ -8,6 +8,16 @@ #ifndef __SOF_DEBUG_GDB_GDB_H__ #define __SOF_DEBUG_GDB_GDB_H__ +/* unconditionally including this header will cause + * problems on architectures such as ARM64 with Zephyr + * since they don't have an entry in arch/. + * + * since GDB debug is only to be used when CONFIG_GDB_DEBUG=y + * we can safely avoid this problem with the below conditional + * definition of the symbols. + */ +#ifdef CONFIG_GDB_DEBUG + #include #include @@ -30,4 +40,6 @@ void gdb_debug_info(unsigned char *str); void gdb_init_debug_exception(void); void gdb_init(void); +#endif /* CONFIG_GDB_DEBUG */ + #endif /* __SOF_DEBUG_GDB_GDB_H__ */ diff --git a/src/include/sof/drivers/edma.h b/src/include/sof/drivers/edma.h index 567e4e8cf044..26039c188648 100644 --- a/src/include/sof/drivers/edma.h +++ b/src/include/sof/drivers/edma.h @@ -98,6 +98,33 @@ #define EDMA0_SAI_CHAN_RX_IRQ 349 #define EDMA0_SAI_CHAN_TX_IRQ 349 +#ifdef CONFIG_IMX93_A55 +/* encase all of these macros in an + * ifdef block to avoid possible future + * naming clashes and pointlessly adding + * macros for all other platforms. + */ +#define EDMA2_SAI3_CHAN_RX 1 +#define EDMA2_SAI3_CHAN_TX 0 +/* EDMA2 (aka EDMA4 in the TRM) supports + * up to 64 channels. + */ +#define EDMA2_CHAN_MAX 64 + +/* need to add SPI_BASE to the INTID as + * the values from the TRM are all SPIs. + */ +#define EDMA2_SAI3_CHAN_RX_IRQ (128 + 32) +#define EDMA2_SAI3_CHAN_TX_IRQ (128 + 32) + +/* SAI3 is connected to EDMA2 through + * lines 60 (TX) and 61 (RX). + */ +#define EDMA2_SAI3_TX_MUX 60 +#define EDMA2_SAI3_RX_MUX 61 + +#endif /* CONFIG_IMX93_A55 */ + /* EDMA doesn't bound channels to IPs, we make use of the first two channels for now */ #define IMX8ULP_EDMA2_CHAN0 0 #define IMX8ULP_EDMA2_CHAN1 1 diff --git a/src/include/sof/drivers/mu.h b/src/include/sof/drivers/mu.h index 3e4dda61ae11..a8b2715c05d4 100644 --- a/src/include/sof/drivers/mu.h +++ b/src/include/sof/drivers/mu.h @@ -19,7 +19,7 @@ enum imx_mu_type { IMX_MU_V2, }; -#ifdef CONFIG_IMX8ULP +#if defined(CONFIG_IMX8ULP) || defined(CONFIG_IMX93_A55) #define IMX_MU_VERSION IMX_MU_V2 #else #define IMX_MU_VERSION IMX_MU_V1 @@ -39,7 +39,7 @@ enum imx_mu_xsr { IMX_MU_RSR = 0x12c, }; -#ifdef CONFIG_IMX8ULP +#if defined(CONFIG_IMX8ULP) || defined(CONFIG_IMX93_A55) /* Transmit Register */ #define IMX_MU_xTRn(x) (0x200 + 4 * (x)) /* Receive Register */ diff --git a/src/include/sof/drivers/sai.h b/src/include/sof/drivers/sai.h index e2eb77b49fcf..2b897943d675 100644 --- a/src/include/sof/drivers/sai.h +++ b/src/include/sof/drivers/sai.h @@ -16,7 +16,7 @@ #include #include -#if defined(CONFIG_IMX8M) || defined(CONFIG_IMX8ULP) +#if defined(CONFIG_IMX8M) || defined(CONFIG_IMX8ULP) || defined(CONFIG_IMX93_A55) #define SAI_OFS 8 #else #define SAI_OFS 0 @@ -129,7 +129,7 @@ #define REG_SAI_CSR_FRDE BIT(0) /* SAI Transmit and Receive Configuration 1 Register */ -#ifdef CONFIG_IMX8M +#if defined(CONFIG_IMX8M) || defined(CONFIG_IMX93_A55) #define REG_SAI_CR1_RFW_MASK 0x7f #else #define REG_SAI_CR1_RFW_MASK 0x3f @@ -237,7 +237,7 @@ #define SAI_FLAG_PMQOS BIT(0) -#ifdef CONFIG_IMX8M +#if defined(CONFIG_IMX8M) || defined(CONFIG_IMX93_A55) #define SAI_FIFO_WORD_SIZE 128 #elif defined CONFIG_IMX8ULP #define SAI_FIFO_WORD_SIZE 16 diff --git a/src/include/sof/ipc/common.h b/src/include/sof/ipc/common.h index 360e8417f4a6..4dc1a043fa9c 100644 --- a/src/include/sof/ipc/common.h +++ b/src/include/sof/ipc/common.h @@ -141,11 +141,12 @@ int ipc_dma_trace_send_position(void); */ void ipc_send_buffer_status_notify(void); +struct dai_data; /** * \brief Configure DAI. * @return 0 on success. */ -int ipc_dai_data_config(struct comp_dev *dev); +int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev); /** * \brief create a IPC boot complete message. @@ -154,6 +155,12 @@ int ipc_dai_data_config(struct comp_dev *dev); */ void ipc_boot_complete_msg(struct ipc_cmd_hdr *header, uint32_t data); +/** + * \brief Send a IPC notification that FW has hit + * a DSP notification. + */ +void ipc_send_panic_notification(void); + /** * \brief Read a compact IPC message or return NULL for normal message. * @return Pointer to the compact message data. diff --git a/src/include/sof/ipc/driver.h b/src/include/sof/ipc/driver.h index aac3b6f8a174..348300a5a6ff 100644 --- a/src/include/sof/ipc/driver.h +++ b/src/include/sof/ipc/driver.h @@ -52,6 +52,12 @@ void ipc_platform_complete_cmd(struct ipc *ipc); */ int ipc_platform_send_msg(const struct ipc_msg *msg); +/** + * \brief Send IPC message to host direct without inserting in msg_list. + * @param msg The IPC message to send to host. + */ +void ipc_platform_send_msg_direct(const struct ipc_msg *msg); + /** * \brief Retrieves the ipc_data_host_buffer allocated by the platform ipc. * @return Pointer to the data. diff --git a/src/include/sof/ipc/msg.h b/src/include/sof/ipc/msg.h index 23d43a227d82..a24fa3711ad0 100644 --- a/src/include/sof/ipc/msg.h +++ b/src/include/sof/ipc/msg.h @@ -115,6 +115,13 @@ void ipc_send_queued_msg(void); */ void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority); +/** + * \brief Send an IPC message directly for emergency. + * @param msg The IPC message to be freed. + * @param data The message data. + */ +void ipc_msg_send_direct(struct ipc_msg *msg, void *data); + /** * \brief Build stream position IPC message. * @param[in,out] posn Stream position message diff --git a/src/include/sof/ipc/topology.h b/src/include/sof/ipc/topology.h index 8ba06ac62fe0..fc42a7559f0a 100644 --- a/src/include/sof/ipc/topology.h +++ b/src/include/sof/ipc/topology.h @@ -56,6 +56,7 @@ int ipc4_create_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma); int ipc4_trigger_chain_dma(struct ipc *ipc, struct ipc4_chain_dma *cdma, bool *delay); int ipc4_process_on_core(uint32_t core, bool blocking); int ipc4_pipeline_complete(struct ipc *ipc, uint32_t comp_id); +int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size); #else #error "No or invalid IPC MAJOR version selected." #endif diff --git a/src/include/sof/lib/ams_msg.h b/src/include/sof/lib/ams_msg.h new file mode 100644 index 000000000000..9c1ad5ce6efb --- /dev/null +++ b/src/include/sof/lib/ams_msg.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2023 Intel Corporation + * + * Author: Ievgen Ganakov + */ + +#ifndef __SOF_LIB_AMS_MSG_H__ +#define __SOF_LIB_AMS_MSG_H__ + +/* AMS messages */ +typedef uint8_t ams_uuid_t[16]; + +/* Key-phrase detected AMS message uuid: 80a11122-b36c-11ed-afa1-0242ac120002*/ +#define AMS_KPD_MSG_UUID { 0x80, 0xa1, 0x11, 0x22, 0xb3, 0x6c, 0x11, 0xed, \ + 0xaf, 0xa1, 0x02, 0x42, 0xac, 0x12, 0x00, 0x02 } + +#endif /* __SOF_LIB_AMS_MSG_H__ */ diff --git a/src/include/sof/lib/dai-legacy.h b/src/include/sof/lib/dai-legacy.h index dcce8238719d..c39219d66888 100644 --- a/src/include/sof/lib/dai-legacy.h +++ b/src/include/sof/lib/dai-legacy.h @@ -543,23 +543,30 @@ static inline const struct dai_info *dai_info_get(void) /** * \brief Configure DMA channel for DAI */ -int dai_config_dma_channel(struct comp_dev *dev, const void *config); +int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void *config); + +/** + * \brief Configure HD Audio DMA params for DAI + */ +void dai_set_link_hda_config(uint16_t *link_config, + struct ipc_config_dai *common_config, + const void *spec_config); /** * \brief Reset DAI DMA config */ -void dai_dma_release(struct comp_dev *dev); +void dai_dma_release(struct dai_data *dd, struct comp_dev *dev); /** * \brief Configure DAI physical interface. */ -int dai_config(struct comp_dev *dev, struct ipc_config_dai *common_config, +int dai_config(struct dai_data *dd, struct comp_dev *dev, struct ipc_config_dai *common_config, const void *spec_config); /** * \brief Assign DAI to a group for simultaneous triggering. */ -int dai_assign_group(struct comp_dev *dev, uint32_t group_id); +int dai_assign_group(struct dai_data *dd, struct comp_dev *dev, uint32_t group_id); /** * \brief dai position for host driver. @@ -569,12 +576,12 @@ int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn); /** * \brief update dai dma position for host driver. */ -void dai_dma_position_update(struct comp_dev *dev); +void dai_dma_position_update(struct dai_data *dd, struct comp_dev *dev); /** * \brief release llp slot */ -void dai_release_llp_slot(struct comp_dev *dev); +void dai_release_llp_slot(struct dai_data *dd); /** @}*/ #endif /* __SOF_LIB_DAI_LEGACY_H__ */ diff --git a/src/include/sof/lib/dai-zephyr.h b/src/include/sof/lib/dai-zephyr.h index e383db19e782..412fe12e1cc7 100644 --- a/src/include/sof/lib/dai-zephyr.h +++ b/src/include/sof/lib/dai-zephyr.h @@ -76,6 +76,16 @@ struct timestamp_ops { struct timestamp_data *tsd); }; +union hdalink_cfg { + uint16_t full; + struct { + uint16_t lchan :4; + uint16_t hchan :4; + uint16_t stream :6; + uint16_t rsvd :1; + uint16_t dir :1; + } part; +}; /** * \brief DAI group information */ @@ -253,22 +263,29 @@ int dai_get_stream_id(struct dai *dai, int direction); /** * \brief Configure DMA channel for DAI */ -int dai_config_dma_channel(struct comp_dev *dev, const void *config); +int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void *config); +/** + * \brief Configure HD Audio DMA params for DAI + */ +void dai_set_link_hda_config(uint16_t *link_config, + struct ipc_config_dai *common_config, + const void *spec_config); /** * \brief Reset DAI DMA config */ -void dai_dma_release(struct comp_dev *dev); +void dai_dma_release(struct dai_data *dd, struct comp_dev *dev); /** * \brief Configure DAI physical interface. */ -int dai_config(struct comp_dev *dev, struct ipc_config_dai *common_cfg, const void *spec_cfg); +int dai_config(struct dai_data *dd, struct comp_dev *dev, + struct ipc_config_dai *common_cfg, const void *spec_cfg); /** * \brief Assign DAI to a group for simultaneous triggering. */ -int dai_assign_group(struct comp_dev *dev, uint32_t group_id); +int dai_assign_group(struct dai_data *dd, struct comp_dev *dev, uint32_t group_id); /** * \brief dai position for host driver. @@ -278,12 +295,12 @@ int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn); /** * \brief update dai dma position for host driver. */ -void dai_dma_position_update(struct comp_dev *dev); +void dai_dma_position_update(struct dai_data *dd, struct comp_dev *dev); /** * \brief release llp slot */ -void dai_release_llp_slot(struct comp_dev *dev); +void dai_release_llp_slot(struct dai_data *dd); /** @}*/ #endif /* __SOF_LIB_DAI_ZEPHYR_H__ */ diff --git a/src/include/sof/lib/notifier.h b/src/include/sof/lib/notifier.h index 99d11648f056..abf893281f70 100644 --- a/src/include/sof/lib/notifier.h +++ b/src/include/sof/lib/notifier.h @@ -58,6 +58,9 @@ struct notify_data { struct notify **arch_notify_get(void); +typedef void (*notifier_callback_t)(void *receiver_data, enum notify_id event_type, + void *caller_data); + /** Register a callback to be run when event 'type' happens. * * The identifier for un-registration is the tuple (receiver_data, @@ -74,9 +77,7 @@ struct notify **arch_notify_get(void); * @param flags see NOTIFIER_FLAG_* above */ int notifier_register(void *receiver_data, void *caller_id_filter, enum notify_id event_type, - void (*callback)(void *receiver_data, enum notify_id event_type, - void *caller_data), - uint32_t flags); + notifier_callback_t callback, uint32_t flags); /** Unregister all callbacks matching that arguments tuple. NULL acts * as a wildcard. diff --git a/src/include/sof/lib_manager.h b/src/include/sof/lib_manager.h index 532f5ed79386..279513f7bb96 100644 --- a/src/include/sof/lib_manager.h +++ b/src/include/sof/lib_manager.h @@ -63,7 +63,7 @@ #define __SOF_LIB_MANAGER_H__ #include -#include +#include #define LIB_MANAGER_MAX_LIBS 16 #define LIB_MANAGER_LIB_ID_SHIFT 12 diff --git a/src/include/sof/math/fir_config.h b/src/include/sof/math/fir_config.h index c40f487c6085..e181c602e00f 100644 --- a/src/include/sof/math/fir_config.h +++ b/src/include/sof/math/fir_config.h @@ -44,7 +44,7 @@ #if XCHAL_HAVE_HIFI2EP == 1 #define FIR_HIFIEP 1 #define FIR_HIFI3 0 -#elif XCHAL_HAVE_HIFI3 == 1 +#elif XCHAL_HAVE_HIFI3 == 1 || XCHAL_HAVE_HIFI4 == 1 #define FIR_HIFI3 1 #define FIR_HIFIEP 0 #else diff --git a/src/include/sof/math/fir_hifi3.h b/src/include/sof/math/fir_hifi3.h index 9a933e0ebee2..a3d4b19ce0ce 100644 --- a/src/include/sof/math/fir_hifi3.h +++ b/src/include/sof/math/fir_hifi3.h @@ -48,10 +48,10 @@ static inline void fir_core_setup_circular(struct fir_state_32x16 *fir) } /* Setup circular for component buffer */ -static inline void fir_comp_setup_circular(const struct audio_stream *buffer) +static inline void fir_comp_setup_circular(const struct audio_stream __sparse_cache *buffer) { - AE_SETCBEGIN0(buffer->addr); - AE_SETCEND0(buffer->end_addr); + AE_SETCBEGIN0(audio_stream_get_addr(buffer)); + AE_SETCEND0(audio_stream_get_end_addr(buffer)); } void fir_get_lrshifts(struct fir_state_32x16 *fir, int *lshift, diff --git a/src/include/sof/samples/audio/smart_amp_test.h b/src/include/sof/samples/audio/smart_amp_test.h index 56b0c01f275a..7f24b5c37de8 100644 --- a/src/include/sof/samples/audio/smart_amp_test.h +++ b/src/include/sof/samples/audio/smart_amp_test.h @@ -31,11 +31,6 @@ struct smart_amp_model_data { uint32_t data_pos; }; -typedef int(*smart_amp_proc)(struct comp_dev *dev, - const struct audio_stream __sparse_cache *source, - const struct audio_stream __sparse_cache *sink, uint32_t frames, - int8_t *chan_map); - /* Each channel map specifies which channel from input (buffer between host * and smart amp - source_chan_map[] or feedback buffer between smart amp and * demux - feedback_chan_map[]) will be copied to specific smart amp output @@ -99,7 +94,6 @@ struct sof_smart_amp_config { #define SMART_AMP_NUM_OUT_PINS 1 struct sof_smart_amp_ipc4_config { - struct ipc4_base_module_cfg base; struct ipc4_input_pin_format input_pins[SMART_AMP_NUM_IN_PINS]; struct ipc4_output_pin_format output_pin; }; diff --git a/src/include/sof/schedule/ll_schedule_domain.h b/src/include/sof/schedule/ll_schedule_domain.h index c6f2b7026471..f555c256398b 100644 --- a/src/include/sof/schedule/ll_schedule_domain.h +++ b/src/include/sof/schedule/ll_schedule_domain.h @@ -48,7 +48,7 @@ struct ll_schedule_domain_ops { void (*domain_clear)(struct ll_schedule_domain *domain); bool (*domain_is_pending)(struct ll_schedule_domain *domain, struct task *task, struct comp_dev **comp); - void (*domain_task_cancel)(struct ll_schedule_domain *domain, uint32_t num_tasks); + void (*domain_task_cancel)(struct ll_schedule_domain *domain, struct task *task); }; struct ll_schedule_domain { @@ -130,10 +130,10 @@ static inline void domain_clear(struct ll_schedule_domain *domain) /* let the domain know that a task has been cancelled */ static inline void domain_task_cancel(struct ll_schedule_domain *domain, - uint32_t num_tasks) + struct task *task) { if (domain->ops->domain_task_cancel) - domain->ops->domain_task_cancel(domain, num_tasks); + domain->ops->domain_task_cancel(domain, task); } static inline int domain_register(struct ll_schedule_domain *domain, diff --git a/src/init/init.c b/src/init/init.c index 7a894e963b12..7a0de9cb1cd5 100644 --- a/src/init/init.c +++ b/src/init/init.c @@ -32,6 +32,7 @@ #include #if CONFIG_IPC_MAJOR_4 #include +#include #endif #ifdef CONFIG_ZEPHYR_LOG #include @@ -338,11 +339,8 @@ int sof_main(int argc, char *argv[]) return start_complete(); } -struct device; - static int sof_init(void) { - return primary_core_init(0, NULL, &sof); } diff --git a/src/ipc/ipc-common.c b/src/ipc/ipc-common.c index be1e53fc6a65..b65407719093 100644 --- a/src/ipc/ipc-common.c +++ b/src/ipc/ipc-common.c @@ -178,6 +178,26 @@ static void schedule_ipc_worker(void) #endif } +void ipc_msg_send_direct(struct ipc_msg *msg, void *data) +{ + struct ipc *ipc = ipc_get(); + k_spinlock_key_t key; + int ret; + + key = k_spin_lock(&ipc->lock); + + /* copy mailbox data to message if not already copied */ + if (msg->tx_size > 0 && msg->tx_size <= SOF_IPC_MSG_MAX_SIZE && + msg->tx_data != data) { + ret = memcpy_s(msg->tx_data, msg->tx_size, data, msg->tx_size); + assert(!ret); + } + + ipc_platform_send_msg_direct(msg); + + k_spin_unlock(&ipc->lock, key); +} + void ipc_msg_send(struct ipc_msg *msg, void *data, bool high_priority) { struct ipc *ipc = ipc_get(); diff --git a/src/ipc/ipc-helper.c b/src/ipc/ipc-helper.c index 085346290070..058795f9865f 100644 --- a/src/ipc/ipc-helper.c +++ b/src/ipc/ipc-helper.c @@ -44,17 +44,12 @@ struct comp_buffer *buffer_new(const struct sof_ipc_buffer *desc) desc->size, desc->comp.pipeline_id, desc->comp.id, desc->flags); /* allocate buffer */ - buffer = buffer_alloc(desc->size, desc->caps, PLATFORM_DCACHE_ALIGN); + buffer = buffer_alloc(desc->size, desc->caps, desc->flags, PLATFORM_DCACHE_ALIGN); if (buffer) { buffer->id = desc->comp.id; buffer->pipeline_id = desc->comp.pipeline_id; buffer->core = desc->comp.core; - buffer->stream.underrun_permitted = desc->flags & - SOF_BUF_UNDERRUN_PERMITTED; - buffer->stream.overrun_permitted = desc->flags & - SOF_BUF_OVERRUN_PERMITTED; - memcpy_s(&buffer->tctx, sizeof(struct tr_ctx), &buffer_tr, sizeof(struct tr_ctx)); } @@ -87,16 +82,16 @@ static void comp_update_params(uint32_t flag, struct comp_buffer __sparse_cache *buffer) { if (flag & BUFF_PARAMS_FRAME_FMT) - params->frame_fmt = buffer->stream.frame_fmt; + params->frame_fmt = audio_stream_get_frm_fmt(&buffer->stream); if (flag & BUFF_PARAMS_BUFFER_FMT) params->buffer_fmt = buffer->buffer_fmt; if (flag & BUFF_PARAMS_CHANNELS) - params->channels = buffer->stream.channels; + params->channels = audio_stream_get_channels(&buffer->stream); if (flag & BUFF_PARAMS_RATE) - params->rate = buffer->stream.rate; + params->rate = audio_stream_get_rate(&buffer->stream); } int comp_verify_params(struct comp_dev *dev, uint32_t flag, @@ -145,7 +140,7 @@ int comp_verify_params(struct comp_dev *dev, uint32_t flag, buffer_set_params(buf_c, params, BUFFER_UPDATE_FORCE); /* set component period frames */ - component_set_nearest_period_frames(dev, buf_c->stream.rate); + component_set_nearest_period_frames(dev, audio_stream_get_rate(&buf_c->stream)); buffer_release(buf_c); } else { @@ -167,7 +162,7 @@ int comp_verify_params(struct comp_dev *dev, uint32_t flag, source_list); buf_c = buffer_acquire(sinkb); - component_set_nearest_period_frames(dev, buf_c->stream.rate); + component_set_nearest_period_frames(dev, audio_stream_get_rate(&buf_c->stream)); buffer_release(buf_c); } diff --git a/src/ipc/ipc-zephyr.c b/src/ipc/ipc-zephyr.c index 975fa503ee4c..85c6656a143c 100644 --- a/src/ipc/ipc-zephyr.c +++ b/src/ipc/ipc-zephyr.c @@ -176,6 +176,19 @@ int ipc_platform_send_msg(const struct ipc_msg *msg) return 0; } +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* prepare the message and copy to mailbox */ + struct ipc_cmd_hdr *hdr = ipc_prepare_to_send(msg); + + intel_adsp_ipc_send_message_emergency(INTEL_ADSP_IPC_HOST_DEV, hdr->pri, hdr->ext); +} + +int ipc_platform_poll_is_host_ready(void) +{ + return intel_adsp_ipc_is_complete(INTEL_ADSP_IPC_HOST_DEV); +} + int platform_ipc_init(struct ipc *ipc) { ipc_set_drvdata(ipc, NULL); diff --git a/src/ipc/ipc3/dai.c b/src/ipc/ipc3/dai.c index bffe3192eb05..decee57299b9 100644 --- a/src/ipc/ipc3/dai.c +++ b/src/ipc/ipc3/dai.c @@ -29,9 +29,13 @@ LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); -int dai_config_dma_channel(struct comp_dev *dev, const void *spec_config) +void dai_set_link_hda_config(uint16_t *link_config, + struct ipc_config_dai *common_config, + const void *spec_config) +{ } + +int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void *spec_config) { - struct dai_data *dd = comp_get_drvdata(dev); const struct sof_ipc_dai_config *config = spec_config; struct ipc_config_dai *dai = &dd->ipc_config; int channel; @@ -95,9 +99,8 @@ int dai_config_dma_channel(struct comp_dev *dev, const void *spec_config) return channel; } -int ipc_dai_data_config(struct comp_dev *dev) +int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev) { - struct dai_data *dd = comp_get_drvdata(dev); struct ipc_config_dai *dai = &dd->ipc_config; struct sof_ipc_dai_config *config = ipc_from_dai_config(dd->dai_spec_config); struct comp_buffer __sparse_cache *buffer_c; @@ -144,7 +147,7 @@ int ipc_dai_data_config(struct comp_dev *dev) dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S32_LE; if (dd->dma_buffer) { buffer_c = buffer_acquire(dd->dma_buffer); - buffer_c->stream.frame_fmt = dev->ipc_config.frame_fmt; + audio_stream_set_frm_fmt(&buffer_c->stream, dev->ipc_config.frame_fmt); buffer_release(buffer_c); } dd->config.burst_elems = dai_get_fifo_depth(dd->dai, dai->direction); @@ -169,7 +172,7 @@ int ipc_dai_data_config(struct comp_dev *dev) dev->ipc_config.frame_fmt = SOF_IPC_FRAME_S32_LE; if (dd->dma_buffer) { buffer_c = buffer_acquire(dd->dma_buffer); - buffer_c->stream.frame_fmt = dev->ipc_config.frame_fmt; + audio_stream_set_frm_fmt(&buffer_c->stream, dev->ipc_config.frame_fmt); buffer_release(buffer_c); } break; @@ -263,10 +266,8 @@ int ipc_comp_dai_config(struct ipc *ipc, struct ipc_config_dai *common_config, return ret; } -void dai_dma_release(struct comp_dev *dev) +void dai_dma_release(struct dai_data *dd, struct comp_dev *dev) { - struct dai_data *dd = comp_get_drvdata(dev); - /* cannot configure DAI while active */ if (dev->state == COMP_STATE_ACTIVE) { comp_info(dev, "dai_config(): Component is in active state. Ignore resetting"); @@ -287,11 +288,10 @@ void dai_dma_release(struct comp_dev *dev) } } -int dai_config(struct comp_dev *dev, struct ipc_config_dai *common_config, +int dai_config(struct dai_data *dd, struct comp_dev *dev, struct ipc_config_dai *common_config, const void *spec_config) { const struct sof_ipc_dai_config *config = spec_config; - struct dai_data *dd = comp_get_drvdata(dev); int ret; /* ignore if message not for this DAI id/type */ @@ -336,7 +336,7 @@ int dai_config(struct comp_dev *dev, struct ipc_config_dai *common_config, if (ret < 0) return ret; - dai_dma_release(dev); + dai_dma_release(dd, dev); } return 0; @@ -353,14 +353,14 @@ int dai_config(struct comp_dev *dev, struct ipc_config_dai *common_config, } #if CONFIG_COMP_DAI_GROUP if (config->group_id) { - ret = dai_assign_group(dev, config->group_id); + ret = dai_assign_group(dd, dev, config->group_id); if (ret) return ret; } #endif /* do nothing for asking for channel free, for compatibility. */ - if (dai_config_dma_channel(dev, spec_config) == DMA_CHAN_INVALID) + if (dai_config_dma_channel(dd, dev, spec_config) == DMA_CHAN_INVALID) return 0; /* allocated dai_config if not yet */ @@ -396,6 +396,6 @@ int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) return 0; } -void dai_dma_position_update(struct comp_dev *dev) { } +void dai_dma_position_update(struct dai_data *dd, struct comp_dev *dev) { } -void dai_release_llp_slot(struct comp_dev *dev) { } +void dai_release_llp_slot(struct dai_data *dd) { } diff --git a/src/ipc/ipc3/handler.c b/src/ipc/ipc3/handler.c index 7d42b58d8ca2..24249f09b86e 100644 --- a/src/ipc/ipc3/handler.c +++ b/src/ipc/ipc3/handler.c @@ -1603,6 +1603,40 @@ void ipc_boot_complete_msg(struct ipc_cmd_hdr *header, uint32_t data) header->dat[1] = data; } +void ipc_send_panic_notification(void) +{ + /* nothing to do */ +} + +static int ipc_fw_ready(void) +{ +#ifdef CONFIG_IMX93_A55 + /* VERY IMPORTANT: + * * due to how the FW is started, i.MX93 has the + * following flow (please note that the host driver + * is blacklisted and inserted later on): + * + * 1) Linux kernel boots and user space becomes + * available. + * 2) FW is started (through Jailhouse) => SOF is running + * 4) Host driver module is inserted. + * 5) Host platform driver sends SOF_IPC_FW_READY and + * expects SOF to send the SOF_IPC_FW_READY + * message, the window regions and the reply + * header in the following order: + * 1) reply structure + * 2) sof_ipc_fw_ready structure + * 3) windows structure + * (all of the above information is written + * contiguously in the hostbox) + */ + return platform_boot_complete(0); +#else + /* any other platform should not receive SOF_IPC_FW_READY from host */ + return -EINVAL; +#endif /* CONFIG_IMX93_A55 */ +} + /* * Global IPC Operations. */ @@ -1663,6 +1697,9 @@ void ipc_cmd(struct ipc_cmd_hdr *_hdr) case SOF_IPC_GLB_DEBUG: ret = ipc_glb_debug_message(hdr->cmd); break; + case SOF_IPC_FW_READY: + ret = ipc_fw_ready(); + break; #if CONFIG_DEBUG case SOF_IPC_GLB_TEST: ret = ipc_glb_test_message(hdr->cmd); diff --git a/src/ipc/ipc4/CMakeLists.txt b/src/ipc/ipc4/CMakeLists.txt index 536c3035822f..7f9d75f654be 100644 --- a/src/ipc/ipc4/CMakeLists.txt +++ b/src/ipc/ipc4/CMakeLists.txt @@ -6,6 +6,7 @@ add_local_sources(sof helper.c logging.c notification.c + ams_helpers.c ) target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/rimage/src/include) diff --git a/src/ipc/ipc4/ams_helpers.c b/src/ipc/ipc4/ams_helpers.c new file mode 100644 index 000000000000..6f21ee3e3623 --- /dev/null +++ b/src/ipc/ipc4/ams_helpers.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Ievgen Ganakov + */ + +#include +#include + +#if CONFIG_AMS + +int ams_helper_register_producer(const struct comp_dev *dev, + uint32_t *ams_uuid_id, + const uint8_t *msg_uuid) +{ + uint16_t mod_id = IPC4_MOD_ID(dev_comp_id(dev)); + uint16_t inst_id = IPC4_INST_ID(dev_comp_id(dev)); + int ret; + + ret = ams_get_message_type_id(msg_uuid, ams_uuid_id); + if (ret) + return ret; + + return ams_register_producer(*ams_uuid_id, mod_id, inst_id); +} + +int ams_helper_unregister_producer(const struct comp_dev *dev, + uint32_t ams_uuid_id) +{ + uint16_t mod_id = IPC4_MOD_ID(dev_comp_id(dev)); + uint16_t inst_id = IPC4_INST_ID(dev_comp_id(dev)); + + return ams_unregister_producer(ams_uuid_id, mod_id, inst_id); +} + +int ams_helper_register_consumer(struct comp_dev *dev, + uint32_t *ams_uuid_id, + const uint8_t *msg_uuid, + ams_msg_callback_fn callback) +{ + uint16_t mod_id = IPC4_MOD_ID(dev_comp_id(dev)); + uint16_t inst_id = IPC4_INST_ID(dev_comp_id(dev)); + int ret; + + ret = ams_get_message_type_id(msg_uuid, ams_uuid_id); + if (ret) + return ret; + + return ams_register_consumer(*ams_uuid_id, mod_id, inst_id, callback, dev); +} + +int ams_helper_unregister_consumer(struct comp_dev *dev, + uint32_t ams_uuid_id, + ams_msg_callback_fn callback) +{ + uint16_t mod_id = IPC4_MOD_ID(dev_comp_id(dev)); + uint16_t inst_id = IPC4_INST_ID(dev_comp_id(dev)); + + return ams_unregister_consumer(ams_uuid_id, mod_id, inst_id, callback); +} + +void ams_helper_prepare_payload(const struct comp_dev *dev, + struct ams_message_payload *payload, + uint32_t ams_uuid_id, + uint8_t *message, + size_t message_size) +{ + uint16_t mod_id = IPC4_MOD_ID(dev_comp_id(dev)); + uint16_t inst_id = IPC4_INST_ID(dev_comp_id(dev)); + + payload->message_type_id = ams_uuid_id; + payload->producer_module_id = mod_id; + payload->producer_instance_id = inst_id; + payload->message_length = message_size; + payload->message = message; +} + +#endif /* CONFIG_AMS */ diff --git a/src/ipc/ipc4/dai.c b/src/ipc/ipc4/dai.c index be2f10eb08b5..e12cdad496da 100644 --- a/src/ipc/ipc4/dai.c +++ b/src/ipc/ipc4/dai.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -30,10 +31,44 @@ LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); -int dai_config_dma_channel(struct comp_dev *dev, const void *spec_config) +void dai_set_link_hda_config(uint16_t *link_config, + struct ipc_config_dai *common_config, + const void *spec_config) +{ +#if defined(CONFIG_ACE_VERSION_2_0) + const struct ipc4_audio_format *out_fmt = common_config->out_fmt; + union hdalink_cfg link_cfg; + + switch (common_config->type) { + case SOF_DAI_INTEL_SSP: + link_cfg.full = 0; + link_cfg.part.dir = common_config->direction; + link_cfg.part.stream = common_config->host_dma_config->stream_id; + break; + case SOF_DAI_INTEL_DMIC: + link_cfg.full = 0; + if (out_fmt->depth == IPC4_DEPTH_16BIT) { + /* 16bit dmic packs two 16bit samples into single 32bit word + * fw needs to adjust channel count to match final sample + * group size + */ + link_cfg.part.hchan = (out_fmt->channels_count - 1) / 2; + } else { + link_cfg.part.hchan = out_fmt->channels_count - 1; + } + link_cfg.part.stream = common_config->host_dma_config->stream_id; + break; + default: + /* other types of DAIs not need link_config */ + return; + } + *link_config = link_cfg.full; +#endif +} + +int dai_config_dma_channel(struct dai_data *dd, struct comp_dev *dev, const void *spec_config) { const struct ipc4_copier_module_cfg *copier_cfg = spec_config; - struct dai_data *dd = comp_get_drvdata(dev); struct ipc_config_dai *dai = &dd->ipc_config; int channel; @@ -42,6 +77,10 @@ int dai_config_dma_channel(struct comp_dev *dev, const void *spec_config) COMPILER_FALLTHROUGH; case SOF_DAI_INTEL_DMIC: channel = 0; +#if defined(CONFIG_ACE_VERSION_2_0) + if (dai->host_dma_config->pre_allocated_by_host) + channel = dai->host_dma_config->dma_channel_id; +#endif break; case SOF_DAI_INTEL_HDA: channel = copier_cfg->gtw_cfg.node_id.f.v_index; @@ -62,9 +101,8 @@ int dai_config_dma_channel(struct comp_dev *dev, const void *spec_config) return channel; } -int ipc_dai_data_config(struct comp_dev *dev) +int ipc_dai_data_config(struct dai_data *dd, struct comp_dev *dev) { - struct dai_data *dd = comp_get_drvdata(dev); struct ipc_config_dai *dai = &dd->ipc_config; struct ipc4_copier_module_cfg *copier_cfg = dd->dai_spec_config; struct dai *dai_p = dd->dai; @@ -138,10 +176,8 @@ int ipc_comp_dai_config(struct ipc *ipc, struct ipc_config_dai *common_config, return 0; } -void dai_dma_release(struct comp_dev *dev) +void dai_dma_release(struct dai_data *dd, struct comp_dev *dev) { - struct dai_data *dd = comp_get_drvdata(dev); - /* cannot configure DAI while active */ if (dev->state == COMP_STATE_ACTIVE) { comp_info(dev, "dai_config(): Component is in active state. Ignore resetting"); @@ -171,17 +207,11 @@ void dai_dma_release(struct comp_dev *dev) */ #if CONFIG_ZEPHYR_NATIVE_DRIVERS /* if reset is after pause dma has already been stopped */ - if (dev->state != COMP_STATE_PAUSED) - dma_stop(dd->chan->dma->z_dev, dd->chan->index); + dma_stop(dd->chan->dma->z_dev, dd->chan->index); - /* remove callback */ - notifier_unregister(dev, dd->chan, NOTIFIER_ID_DMA_COPY); dma_release_channel(dd->chan->dma->z_dev, dd->chan->index); #else dma_stop_legacy(dd->chan); - - /* remove callback */ - notifier_unregister(dev, dd->chan, NOTIFIER_ID_DMA_COPY); dma_channel_put_legacy(dd->chan); #endif dd->chan->dev_data = NULL; @@ -189,9 +219,8 @@ void dai_dma_release(struct comp_dev *dev) } } -void dai_release_llp_slot(struct comp_dev *dev) +void dai_release_llp_slot(struct dai_data *dd) { - struct dai_data *dd = comp_get_drvdata(dev); struct ipc4_llp_reading_slot slot; k_spinlock_key_t key; @@ -253,9 +282,8 @@ static int dai_get_unused_llp_slot(struct comp_dev *dev, return offset; } -static int dai_init_llp_info(struct comp_dev *dev) +static int dai_init_llp_info(struct dai_data *dd, struct comp_dev *dev) { - struct dai_data *dd = comp_get_drvdata(dev); struct ipc4_copier_module_cfg *copier_cfg; union ipc4_connector_node_id node; int ret; @@ -283,11 +311,10 @@ static int dai_init_llp_info(struct comp_dev *dev) return 0; } -int dai_config(struct comp_dev *dev, struct ipc_config_dai *common_config, +int dai_config(struct dai_data *dd, struct comp_dev *dev, struct ipc_config_dai *common_config, const void *spec_config) { const struct ipc4_copier_module_cfg *copier_cfg = spec_config; - struct dai_data *dd = comp_get_drvdata(dev); int size; int ret; @@ -313,14 +340,14 @@ int dai_config(struct comp_dev *dev, struct ipc_config_dai *common_config, #if CONFIG_COMP_DAI_GROUP if (common_config->group_id) { - ret = dai_assign_group(dev, common_config->group_id); + ret = dai_assign_group(dd, dev, common_config->group_id); if (ret) return ret; } #endif /* do nothing for asking for channel free, for compatibility. */ - if (dai_config_dma_channel(dev, spec_config) == DMA_CHAN_INVALID) + if (dai_config_dma_channel(dd, dev, spec_config) == DMA_CHAN_INVALID) return 0; dd->dai_dev = dev; @@ -342,7 +369,7 @@ int dai_config(struct comp_dev *dev, struct ipc_config_dai *common_config, } } - ret = dai_init_llp_info(dev); + ret = dai_init_llp_info(dd, dev); if (ret < 0) return ret; @@ -350,9 +377,9 @@ int dai_config(struct comp_dev *dev, struct ipc_config_dai *common_config, } #if CONFIG_ZEPHYR_NATIVE_DRIVERS -int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) +int dai_zephyr_position(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_posn *posn) { - struct dai_data *dd = comp_get_drvdata(dev); struct dma_status status; int ret; @@ -371,9 +398,15 @@ int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) return 0; } -void dai_dma_position_update(struct comp_dev *dev) +int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) { struct dai_data *dd = comp_get_drvdata(dev); + + return dai_zephyr_position(dd, dev, posn); +} + +void dai_dma_position_update(struct dai_data *dd, struct comp_dev *dev) +{ struct ipc4_llp_reading_slot slot; struct dma_status status; int ret; @@ -396,9 +429,9 @@ void dai_dma_position_update(struct comp_dev *dev) mailbox_sw_regs_write(dd->slot_info.reg_offset, &slot, sizeof(slot)); } #else -int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) +int dai_zephyr_position(struct dai_data *dd, struct comp_dev *dev, + struct sof_ipc_stream_posn *posn) { - struct dai_data *dd = comp_get_drvdata(dev); struct dma_chan_status status; /* total processed bytes count */ @@ -413,9 +446,15 @@ int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) return 0; } -void dai_dma_position_update(struct comp_dev *dev) +int dai_position(struct comp_dev *dev, struct sof_ipc_stream_posn *posn) { struct dai_data *dd = comp_get_drvdata(dev); + + return dai_zephyr_position(dd, dev, posn); +} + +void dai_dma_position_update(struct dai_data *dd, struct comp_dev *dev) +{ struct ipc4_llp_reading_slot slot; struct dma_chan_status status; uint32_t llp_data[2]; diff --git a/src/ipc/ipc4/handler.c b/src/ipc/ipc4/handler.c index bc03ee6ab37b..640b0594fb47 100644 --- a/src/ipc/ipc4/handler.c +++ b/src/ipc/ipc4/handler.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include @@ -42,6 +42,17 @@ #include #include +/* Command format errors during fuzzing are reported for virtually all + * commands, and the resulting flood of logging becomes a severe + * performance penalty (i.e. we get a lot less fuzzing done per CPU + * cycle). + */ +#ifdef CONFIG_ARCH_POSIX_LIBFUZZER +#define ipc_cmd_err(...) +#else +#define ipc_cmd_err(...) tr_err(__VA_ARGS__) +#endif + LOG_MODULE_DECLARE(ipc, CONFIG_SOF_LOG_LEVEL); struct ipc4_msg_data { @@ -56,9 +67,7 @@ static struct ipc4_msg_data msg_data; /* fw sends a fw ipc message to send the status of the last host ipc message */ static struct ipc_msg msg_reply; -#ifdef CONFIG_LOG_BACKEND_ADSP_MTRACE static struct ipc_msg msg_notify; -#endif /* * Global IPC Operations. @@ -127,25 +136,25 @@ static int ipc4_pcm_params(struct ipc_comp_dev *pcm_dev) /* sanity check comp */ if (!pcm_dev->cd->pipeline) { - tr_err(&ipc_tr, "ipc: comp %d pipeline not found", pcm_dev->id); + ipc_cmd_err(&ipc_tr, "ipc: comp %d pipeline not found", pcm_dev->id); return -EINVAL; } /* configure pipeline audio params */ err = ipc4_pipeline_params(pcm_dev->cd->pipeline, pcm_dev->cd); if (err < 0) { - tr_err(&ipc_tr, "ipc: pipe %d comp %d params failed %d", - pcm_dev->cd->pipeline->pipeline_id, - pcm_dev->cd->pipeline->comp_id, err); + ipc_cmd_err(&ipc_tr, "ipc: pipe %d comp %d params failed %d", + pcm_dev->cd->pipeline->pipeline_id, + pcm_dev->cd->pipeline->comp_id, err); goto error; } /* prepare pipeline audio params */ err = pipeline_prepare(pcm_dev->cd->pipeline, pcm_dev->cd); if (err < 0) { - tr_err(&ipc_tr, "ipc: pipe %d comp %d prepare failed %d", - pcm_dev->cd->pipeline->pipeline_id, - pcm_dev->cd->pipeline->comp_id, err); + ipc_cmd_err(&ipc_tr, "ipc: pipe %d comp %d prepare failed %d", + pcm_dev->cd->pipeline->pipeline_id, + pcm_dev->cd->pipeline->comp_id, err); goto error; } @@ -154,9 +163,9 @@ static int ipc4_pcm_params(struct ipc_comp_dev *pcm_dev) error: reset_err = pipeline_reset(pcm_dev->cd->pipeline, pcm_dev->cd); if (reset_err < 0) - tr_err(&ipc_tr, "ipc: pipe %d comp %d reset failed %d", - pcm_dev->cd->pipeline->pipeline_id, - pcm_dev->cd->pipeline->comp_id, reset_err); + ipc_cmd_err(&ipc_tr, "ipc: pipe %d comp %d reset failed %d", + pcm_dev->cd->pipeline->pipeline_id, + pcm_dev->cd->pipeline->comp_id, reset_err); return err; } @@ -228,7 +237,7 @@ static int set_pipeline_state(struct ipc_comp_dev *ppl_icd, uint32_t cmd, host = ipc_get_comp_by_id(ipc, host_id); if (!host) { - tr_err(&ipc_tr, "ipc: comp host with ID %d not found", host_id); + ipc_cmd_err(&ipc_tr, "ipc: comp host with ID %d not found", host_id); return IPC4_INVALID_RESOURCE_ID; } } @@ -251,7 +260,7 @@ static int set_pipeline_state(struct ipc_comp_dev *ppl_icd, uint32_t cmd, cmd = COMP_TRIGGER_PRE_RELEASE; break; default: - tr_err(&ipc_tr, "ipc: current status %d", status); + ipc_cmd_err(&ipc_tr, "ipc: current status %d", status); return IPC4_INVALID_REQUEST; } break; @@ -270,15 +279,15 @@ static int set_pipeline_state(struct ipc_comp_dev *ppl_icd, uint32_t cmd, case COMP_STATE_PAUSED: ret = pipeline_trigger(host->cd->pipeline, host->cd, COMP_TRIGGER_STOP); if (ret < 0) { - tr_err(&ipc_tr, "ipc: comp %d trigger 0x%x failed %d", - ppl_icd->id, cmd, ret); + ipc_cmd_err(&ipc_tr, "ipc: comp %d trigger 0x%x failed %d", + ppl_icd->id, cmd, ret); return IPC4_PIPELINE_STATE_NOT_SET; } if (ret == PPL_STATUS_SCHEDULED) *delayed = true; break; default: - tr_err(&ipc_tr, "ipc: invalid status %d for RESET", status); + ipc_cmd_err(&ipc_tr, "ipc: invalid status %d for RESET", status); return IPC4_INVALID_REQUEST; } @@ -317,14 +326,14 @@ static int set_pipeline_state(struct ipc_comp_dev *ppl_icd, uint32_t cmd, case SOF_IPC4_PIPELINE_STATE_SAVED: case SOF_IPC4_PIPELINE_STATE_ERROR_STOP: default: - tr_err(&ipc_tr, "ipc: unsupported trigger cmd 0x%x", cmd); + ipc_cmd_err(&ipc_tr, "ipc: unsupported trigger cmd 0x%x", cmd); return IPC4_INVALID_REQUEST; } /* trigger the component */ ret = pipeline_trigger(host->cd->pipeline, host->cd, cmd); if (ret < 0) { - tr_err(&ipc_tr, "ipc: comp %d trigger 0x%x failed %d", ppl_icd->id, cmd, ret); + ipc_cmd_err(&ipc_tr, "ipc: comp %d trigger 0x%x failed %d", ppl_icd->id, cmd, ret); ret = IPC4_PIPELINE_STATE_NOT_SET; } else if (ret == PPL_STATUS_SCHEDULED) { *delayed = true; @@ -345,7 +354,7 @@ static void ipc_compound_pre_start(int msg_id) static void ipc_compound_post_start(uint32_t msg_id, int ret, bool delayed) { if (ret) { - tr_err(&ipc_tr, "failed to process msg %d status %d", msg_id, ret); + ipc_cmd_err(&ipc_tr, "failed to process msg %d status %d", msg_id, ret); atomic_set(&msg_data.delayed_reply, 0); return; } @@ -358,7 +367,7 @@ static void ipc_compound_post_start(uint32_t msg_id, int ret, bool delayed) static void ipc_compound_msg_done(uint32_t msg_id, int error) { if (!atomic_read(&msg_data.delayed_reply)) { - tr_err(&ipc_tr, "unexpected delayed reply"); + ipc_cmd_err(&ipc_tr, "unexpected delayed reply"); return; } @@ -379,7 +388,7 @@ static int ipc_wait_for_compound_msg(void) k_sleep(Z_TIMEOUT_US(250)); if (!try_count--) { - tr_err(&ipc_tr, "failed to wait schedule thread"); + ipc_cmd_err(&ipc_tr, "failed to wait schedule thread"); return IPC4_FAILURE; } } @@ -421,7 +430,7 @@ static int ipc4_set_pipeline_state(struct ipc4_message_request *ipc4) ppl_icd = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, ppl_id[i]); if (!ppl_icd) { - tr_err(&ipc_tr, "ipc: comp %d not found", ppl_id[i]); + ipc_cmd_err(&ipc_tr, "ipc: comp %d not found", ppl_id[i]); return IPC4_INVALID_RESOURCE_ID; } @@ -526,8 +535,8 @@ static int ipc4_process_ipcgtw_cmd(struct ipc4_message_request *ipc4) * quite weird: seems one extra copying can be eliminated. */ - err = ipcgtw_process_cmd((const struct ipc4_ipcgtw_cmd *)ipc4, ipc->comp_data, - &reply_size); + err = copier_ipcgtw_process((const struct ipc4_ipcgtw_cmd *)ipc4, ipc->comp_data, + &reply_size); /* reply size is returned in header extension dword */ msg_reply.extension = reply_size; @@ -536,8 +545,8 @@ static int ipc4_process_ipcgtw_cmd(struct ipc4_message_request *ipc4) if (msg_reply.tx_data) { msg_reply.tx_size = reply_size; } else { - tr_err(&ipc_tr, "failed to allocate %u bytes for msg_reply.tx_data", - reply_size); + ipc_cmd_err(&ipc_tr, "failed to allocate %u bytes for msg_reply.tx_data", + reply_size); msg_reply.extension = 0; return IPC4_OUT_OF_MEMORY; } @@ -545,7 +554,7 @@ static int ipc4_process_ipcgtw_cmd(struct ipc4_message_request *ipc4) return err < 0 ? IPC4_FAILURE : IPC4_SUCCESS; #else - tr_err(&ipc_tr, "CONFIG_IPC4_GATEWAY is disabled"); + ipc_cmd_err(&ipc_tr, "CONFIG_IPC4_GATEWAY is disabled"); return IPC4_UNAVAILABLE; #endif } @@ -563,7 +572,7 @@ static int ipc4_process_glb_message(struct ipc4_message_request *ipc4) case SOF_IPC4_GLB_PERF_MEASUREMENTS_CMD: case SOF_IPC4_GLB_LOAD_MULTIPLE_MODULES: case SOF_IPC4_GLB_UNLOAD_MULTIPLE_MODULES: - tr_err(&ipc_tr, "not implemented ipc message type %d", type); + ipc_cmd_err(&ipc_tr, "not implemented ipc message type %d", type); ret = IPC4_UNAVAILABLE; break; @@ -586,7 +595,7 @@ static int ipc4_process_glb_message(struct ipc4_message_request *ipc4) case SOF_IPC4_GLB_GET_PIPELINE_CONTEXT_SIZE: case SOF_IPC4_GLB_SAVE_PIPELINE: case SOF_IPC4_GLB_RESTORE_PIPELINE: - tr_err(&ipc_tr, "not implemented ipc message type %d", type); + ipc_cmd_err(&ipc_tr, "not implemented ipc message type %d", type); ret = IPC4_UNAVAILABLE; break; @@ -597,13 +606,13 @@ static int ipc4_process_glb_message(struct ipc4_message_request *ipc4) break; #endif case SOF_IPC4_GLB_INTERNAL_MESSAGE: - tr_err(&ipc_tr, "not implemented ipc message type %d", type); + ipc_cmd_err(&ipc_tr, "not implemented ipc message type %d", type); ret = IPC4_UNAVAILABLE; break; /* Notification (FW to SW driver) */ case SOF_IPC4_GLB_NOTIFICATION: - tr_err(&ipc_tr, "not implemented ipc message type %d", type); + ipc_cmd_err(&ipc_tr, "not implemented ipc message type %d", type); ret = IPC4_UNAVAILABLE; break; @@ -612,7 +621,7 @@ static int ipc4_process_glb_message(struct ipc4_message_request *ipc4) break; default: - tr_err(&ipc_tr, "unsupported ipc message type %d", type); + ipc_cmd_err(&ipc_tr, "unsupported ipc message type %d", type); ret = IPC4_UNAVAILABLE; break; } @@ -649,9 +658,9 @@ static int ipc4_init_module_instance(struct ipc4_message_request *ipc4) dev = comp_new_ipc4(&module_init); if (!dev) { - tr_err(&ipc_tr, "error: failed to init module %x : %x", - (uint32_t)module_init.primary.r.module_id, - (uint32_t)module_init.primary.r.instance_id); + ipc_cmd_err(&ipc_tr, "error: failed to init module %x : %x", + (uint32_t)module_init.primary.r.module_id, + (uint32_t)module_init.primary.r.instance_id); return IPC4_MOD_NOT_INITIALIZED; } @@ -762,7 +771,7 @@ static int ipc4_get_large_config_module_instance(struct ipc4_message_request *ip msg_reply.tx_size = data_offset; msg_reply.tx_data = response_buffer; } else { - tr_err(&ipc_tr, "error: failed to allocate tx_data"); + ipc_cmd_err(&ipc_tr, "error: failed to allocate tx_data"); ret = IPC4_OUT_OF_MEMORY; } @@ -810,9 +819,9 @@ static int ipc4_set_large_config_module_instance(struct ipc4_message_request *ip config.extension.r.data_off_size, (const char *)MAILBOX_HOSTBOX_BASE); if (ret < 0) { - tr_err(&ipc_tr, "failed to set large_config_module_instance %x : %x", - (uint32_t)config.primary.r.module_id, - (uint32_t)config.primary.r.instance_id); + ipc_cmd_err(&ipc_tr, "failed to set large_config_module_instance %x : %x", + (uint32_t)config.primary.r.module_id, + (uint32_t)config.primary.r.instance_id); ret = IPC4_INVALID_RESOURCE_ID; } @@ -835,9 +844,9 @@ static int ipc4_delete_module_instance(struct ipc4_message_request *ipc4) comp_id = IPC4_COMP_ID(module.primary.r.module_id, module.primary.r.instance_id); ret = ipc_comp_free(ipc, comp_id); if (ret < 0) { - tr_err(&ipc_tr, "failed to delete module instance %x : %x", - (uint32_t)module.primary.r.module_id, - (uint32_t)module.primary.r.instance_id); + ipc_cmd_err(&ipc_tr, "failed to delete module instance %x : %x", + (uint32_t)module.primary.r.module_id, + (uint32_t)module.primary.r.instance_id); ret = IPC4_INVALID_RESOURCE_ID; } @@ -861,7 +870,7 @@ static int ipc4_module_process_d0ix(struct ipc4_message_request *ipc4) /* only module 0 can be used to set d0ix state */ if (d0ix.primary.r.module_id || d0ix.primary.r.instance_id) { - tr_err(&ipc_tr, "invalid resource id %x : %x", module_id, instance_id); + ipc_cmd_err(&ipc_tr, "invalid resource id %x : %x", module_id, instance_id); return IPC4_INVALID_RESOURCE_ID; } @@ -890,7 +899,7 @@ static int ipc4_module_process_dx(struct ipc4_message_request *ipc4) /* only module 0 can be used to set dx state */ if (module_id || instance_id) { - tr_err(&ipc_tr, "invalid resource id %x : %x", module_id, instance_id); + ipc_cmd_err(&ipc_tr, "invalid resource id %x : %x", module_id, instance_id); return IPC4_INVALID_RESOURCE_ID; } @@ -903,8 +912,8 @@ static int ipc4_module_process_dx(struct ipc4_message_request *ipc4) /* check if core enable mask is valid */ if (dx_info.core_mask > MASK(CONFIG_CORE_COUNT - 1, 0)) { - tr_err(&ipc_tr, "ipc4_module_process_dx: CONFIG_CORE_COUNT: %d < core enable mask: %d", - CONFIG_CORE_COUNT, dx_info.core_mask); + ipc_cmd_err(&ipc_tr, "ipc4_module_process_dx: CONFIG_CORE_COUNT: %d < core enable mask: %d", + CONFIG_CORE_COUNT, dx_info.core_mask); return IPC4_ERROR_INVALID_PARAM; } @@ -912,7 +921,7 @@ static int ipc4_module_process_dx(struct ipc4_message_request *ipc4) if ((dx_info.core_mask & BIT(PLATFORM_PRIMARY_CORE_ID)) && (dx_info.dx_mask & BIT(PLATFORM_PRIMARY_CORE_ID))) { /* core0 can't be activated more, it's already active since we got here */ - tr_err(&ipc_tr, "Core0 is already active"); + ipc_cmd_err(&ipc_tr, "Core0 is already active"); return IPC4_BAD_STATE; } @@ -924,13 +933,13 @@ static int ipc4_module_process_dx(struct ipc4_message_request *ipc4) if (dx_info.dx_mask & BIT(core_id)) { ret = cpu_enable_core(core_id); if (ret != 0) { - tr_err(&ipc_tr, "failed to enable core %d", core_id); + ipc_cmd_err(&ipc_tr, "failed to enable core %d", core_id); return IPC4_FAILURE; } } else { cpu_disable_core(core_id); if (cpu_is_core_enabled(core_id)) { - tr_err(&ipc_tr, "failed to disable core %d", core_id); + ipc_cmd_err(&ipc_tr, "failed to disable core %d", core_id); return IPC4_FAILURE; } } @@ -939,13 +948,13 @@ static int ipc4_module_process_dx(struct ipc4_message_request *ipc4) /* Deactivating primary core if requested. */ if (dx_info.core_mask & BIT(PLATFORM_PRIMARY_CORE_ID)) { if (cpu_enabled_cores() & ~BIT(PLATFORM_PRIMARY_CORE_ID)) { - tr_err(&ipc_tr, "secondary cores 0x%x still active", - cpu_enabled_cores()); + ipc_cmd_err(&ipc_tr, "secondary cores 0x%x still active", + cpu_enabled_cores()); return IPC4_BUSY; } if (is_any_ppl_active()) { - tr_err(&ipc_tr, "some pipelines are still active"); + ipc_cmd_err(&ipc_tr, "some pipelines are still active"); return IPC4_BUSY; } @@ -1052,6 +1061,17 @@ void ipc_boot_complete_msg(struct ipc_cmd_hdr *header, uint32_t data) header->ext = 0; } +void ipc_send_panic_notification(void) +{ + msg_notify.header = SOF_IPC4_NOTIF_HEADER(SOF_IPC4_EXCEPTION_CAUGHT); + msg_notify.extension = cpu_get_id(); + msg_notify.tx_size = 0; + msg_notify.tx_data = NULL; + list_init(&msg_notify.list); + + ipc_msg_send_direct(&msg_notify, NULL); +} + #ifdef CONFIG_LOG_BACKEND_ADSP_MTRACE static bool is_notification_queued(void) @@ -1130,16 +1150,16 @@ void ipc_cmd(struct ipc_cmd_hdr *_hdr) case SOF_IPC4_MESSAGE_TARGET_FW_GEN_MSG: err = ipc4_process_glb_message(in); if (err) - tr_err(&ipc_tr, "ipc4: FW_GEN_MSG failed with err %d", err); + ipc_cmd_err(&ipc_tr, "ipc4: FW_GEN_MSG failed with err %d", err); break; case SOF_IPC4_MESSAGE_TARGET_MODULE_MSG: err = ipc4_process_module_message(in); if (err) - tr_err(&ipc_tr, "ipc4: MODULE_MSG failed with err %d", err); + ipc_cmd_err(&ipc_tr, "ipc4: MODULE_MSG failed with err %d", err); break; default: /* should not reach here as we only have 2 message types */ - tr_err(&ipc_tr, "ipc4: invalid target %d", target); + ipc_cmd_err(&ipc_tr, "ipc4: invalid target %d", target); err = IPC4_UNKNOWN_MESSAGE_TYPE; } @@ -1161,7 +1181,7 @@ void ipc_cmd(struct ipc_cmd_hdr *_hdr) return; if (ipc_wait_for_compound_msg() != 0) { - tr_err(&ipc_tr, "ipc4: failed to send delayed reply"); + ipc_cmd_err(&ipc_tr, "ipc4: failed to send delayed reply"); err = IPC4_FAILURE; } diff --git a/src/ipc/ipc4/helper.c b/src/ipc/ipc4/helper.c index fa89c7abc35e..00f1bf4f8866 100644 --- a/src/ipc/ipc4/helper.c +++ b/src/ipc/ipc4/helper.c @@ -20,8 +20,14 @@ #include #include #include -#ifdef __ZEPHYR__ -#include /* for IMR_BOOT_LDR_MANIFEST_BASE */ + +/* TODO: Remove platform-specific code, see https://github.com/thesofproject/sof/issues/7549 */ +#if defined(CONFIG_SOC_SERIES_INTEL_ACE) || defined(CONFIG_INTEL_ADSP_CAVS) +#define RIMAGE_MANIFEST 1 +#endif + +#ifdef RIMAGE_MANIFEST +#include #endif #include @@ -98,10 +104,18 @@ struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_init) ipc_config.pipeline_id = module_init->extension.r.ppl_instance_id; ipc_config.core = module_init->extension.r.core_id; +#if CONFIG_ZEPHYR_DP_SCHEDULER if (module_init->extension.r.proc_domain) ipc_config.proc_domain = COMP_PROCESSING_DOMAIN_DP; else ipc_config.proc_domain = COMP_PROCESSING_DOMAIN_LL; +#else /* CONFIG_ZEPHYR_DP_SCHEDULER */ + if (module_init->extension.r.proc_domain) { + tr_err(&ipc_tr, "ipc: DP scheduling is disabled, cannot create comp %d", comp_id); + return NULL; + } + ipc_config.proc_domain = COMP_PROCESSING_DOMAIN_LL; +#endif /* CONFIG_ZEPHYR_DP_SCHEDULER */ dcache_invalidate_region((__sparse_force void __sparse_cache *)MAILBOX_HOSTBOX_BASE, MAILBOX_HOSTBOX_SIZE); @@ -127,6 +141,16 @@ struct comp_dev *comp_new_ipc4(struct ipc4_module_init_instance *module_init) return dev; } +static struct ipc_comp_dev *get_comp(struct ipc *ipc, uint16_t type, uint32_t id) +{ + struct ipc_comp_dev *c = ipc_get_comp_by_id(ipc, id); + + if (c && c->type == type) + return c; + + return NULL; +} + struct ipc_comp_dev *ipc_get_comp_by_ppl_id(struct ipc *ipc, uint16_t type, uint32_t ppl_id) { struct ipc_comp_dev *icd; @@ -160,10 +184,9 @@ static int ipc4_create_pipeline(struct ipc4_pipeline_create *pipe_desc) struct ipc *ipc = ipc_get(); /* check whether pipeline id is already taken or in use */ - ipc_pipe = ipc_get_comp_by_ppl_id(ipc, COMP_TYPE_PIPELINE, - pipe_desc->primary.r.instance_id); + ipc_pipe = ipc_get_comp_by_id(ipc, pipe_desc->primary.r.instance_id); if (ipc_pipe) { - tr_err(&ipc_tr, "ipc: pipeline id is already taken, pipe_desc->instance_id = %u", + tr_err(&ipc_tr, "ipc: comp id is already taken, pipe_desc->instance_id = %u", (uint32_t)pipe_desc->primary.r.instance_id); return IPC4_INVALID_RESOURCE_ID; } @@ -275,7 +298,7 @@ int ipc_pipeline_free(struct ipc *ipc, uint32_t comp_id) int ret; /* check whether pipeline exists */ - ipc_pipe = ipc_get_comp_by_id(ipc, comp_id); + ipc_pipe = get_comp(ipc, COMP_TYPE_PIPELINE, comp_id); if (!ipc_pipe) return IPC4_INVALID_RESOURCE_ID; @@ -600,7 +623,7 @@ int ipc4_pipeline_complete(struct ipc *ipc, uint32_t comp_id) struct ipc_comp_dev *ipc_pipe; int ret; - ipc_pipe = ipc_get_comp_by_id(ipc, comp_id); + ipc_pipe = get_comp(ipc, COMP_TYPE_PIPELINE, comp_id); /* Pass IPC to target core */ if (!cpu_is_me(ipc_pipe->core)) @@ -677,11 +700,20 @@ const struct comp_driver *ipc4_get_drv(uint8_t *uuid) const struct comp_driver *ipc4_get_comp_drv(int module_id) { - struct sof_man_fw_desc *desc = (struct sof_man_fw_desc *)IMR_BOOT_LDR_MANIFEST_BASE; + struct sof_man_fw_desc *desc = NULL; const struct comp_driver *drv; struct sof_man_module *mod; int entry_index; +#ifdef RIMAGE_MANIFEST + desc = (struct sof_man_fw_desc *)IMR_BOOT_LDR_MANIFEST_BASE; +#else + /* Non-rimage platforms have no component facility yet. This + * needs to move to the platform layer. + */ + return NULL; +#endif + uint32_t lib_idx = LIB_MANAGER_GET_LIB_ID(module_id); if (lib_idx == 0) { @@ -720,14 +752,9 @@ const struct comp_driver *ipc4_get_comp_drv(int module_id) struct comp_dev *ipc4_get_comp_dev(uint32_t comp_id) { - struct ipc *ipc = ipc_get(); - struct ipc_comp_dev *icd; - - icd = ipc_get_comp_by_id(ipc, comp_id); - if (!icd) - return NULL; + struct ipc_comp_dev *icd = get_comp(ipc_get(), COMP_TYPE_COMPONENT, comp_id); - return icd->cd; + return icd ? icd->cd : NULL; } int ipc4_add_comp_dev(struct comp_dev *dev) @@ -735,6 +762,13 @@ int ipc4_add_comp_dev(struct comp_dev *dev) struct ipc *ipc = ipc_get(); struct ipc_comp_dev *icd; + /* check id for duplicates */ + icd = ipc_get_comp_by_id(ipc, dev->ipc_config.id); + if (icd) { + tr_err(&ipc_tr, "ipc: duplicate component ID"); + return IPC4_INVALID_RESOURCE_ID; + } + /* allocate the IPC component container */ icd = rzalloc(SOF_MEM_ZONE_RUNTIME_SHARED, 0, SOF_MEM_CAPS_RAM, sizeof(struct ipc_comp_dev)); @@ -755,3 +789,17 @@ int ipc4_add_comp_dev(struct comp_dev *dev) return IPC4_SUCCESS; }; + +int ipc4_find_dma_config(struct ipc_config_dai *dai, uint8_t *data_buffer, uint32_t size) +{ +#if defined(CONFIG_ACE_VERSION_2_0) + uint32_t *dma_config_id = GET_IPC_DMA_CONFIG_ID(data_buffer, size); + + if (*dma_config_id != GTW_DMA_CONFIG_ID) + return IPC4_INVALID_REQUEST; + + dai->host_dma_config = GET_IPC_DMA_CONFIG(data_buffer, size); +#endif + return IPC4_SUCCESS; +} + diff --git a/src/lib/ams.c b/src/lib/ams.c index 7da92f23b5cc..825e265644bc 100644 --- a/src/lib/ams.c +++ b/src/lib/ams.c @@ -58,14 +58,15 @@ static struct uuid_idx __sparse_cache *ams_find_uuid_entry_by_uuid(struct ams_sh /* try to find existing entry */ for (index = 0; index < AMS_SERVICE_UUID_TABLE_SIZE; index++) { - if (memcmp((void *)uuid_table[index].message_uuid, uuid, UUID_SIZE) == 0) + if (memcmp((__sparse_force void *)uuid_table[index].message_uuid, + uuid, UUID_SIZE) == 0) return &uuid_table[index]; } /* and add new one if needed */ for (index = 0; index < AMS_SERVICE_UUID_TABLE_SIZE; index++) { if (uuid_table[index].message_type_id == AMS_INVALID_MSG_TYPE) { - int ec = memcpy_s((void *)uuid_table[index].message_uuid, + int ec = memcpy_s((__sparse_force void *)uuid_table[index].message_uuid, sizeof(uuid_table[index].message_uuid), uuid, UUID_SIZE); if (ec != 0) { @@ -285,7 +286,7 @@ static uint32_t ams_push_slot(struct ams_shared_context __sparse_cache *ctx_shar for (uint32_t i = 0; i < ARRAY_SIZE(ctx_shared->slots); ++i) { if (ctx_shared->slot_uses[i] == 0) { - err = memcpy_s((void *)ctx_shared->slots[i].u.msg_raw, + err = memcpy_s((__sparse_force void *)ctx_shared->slots[i].u.msg_raw, sizeof(ctx_shared->slots[i].u.msg_raw), msg, AMS_MESSAGE_SIZE(msg)); diff --git a/src/lib/dai.c b/src/lib/dai.c index b04c9d118832..2cdf0c9192a0 100644 --- a/src/lib/dai.c +++ b/src/lib/dai.c @@ -170,15 +170,27 @@ static void dai_set_device_params(struct dai *d) switch (d->type) { case SOF_DAI_INTEL_SSP: d->dma_dev = DMA_DEV_SSP; +#ifdef CONFIG_DMA_INTEL_ADSP_GPDMA d->dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP; +#else + d->dma_caps = DMA_CAP_HDA; +#endif break; case SOF_DAI_INTEL_DMIC: d->dma_dev = DMA_DEV_DMIC; +#ifdef CONFIG_DMA_INTEL_ADSP_GPDMA d->dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP; +#else + d->dma_caps = DMA_CAP_HDA; +#endif break; case SOF_DAI_INTEL_ALH: d->dma_dev = DMA_DEV_ALH; +#ifdef CONFIG_DMA_INTEL_ADSP_GPDMA d->dma_caps = DMA_CAP_GP_LP | DMA_CAP_GP_HP; +#else + d->dma_caps = DMA_CAP_HDA; +#endif break; case SOF_DAI_INTEL_HDA: d->dma_dev = DMA_DEV_HDA; diff --git a/src/lib/dma.c b/src/lib/dma.c index 58aa64dc841e..6115cfba1e85 100644 --- a/src/lib/dma.c +++ b/src/lib/dma.c @@ -378,3 +378,24 @@ int dma_buffer_copy_to(struct comp_buffer __sparse_cache *source, return ret; } + +int dma_buffer_copy_from_no_consume(struct comp_buffer __sparse_cache *source, + struct comp_buffer __sparse_cache *sink, + dma_process_func process, uint32_t source_bytes) +{ + struct audio_stream __sparse_cache *istream = &source->stream; + uint32_t samples = source_bytes / + audio_stream_sample_bytes(istream); + uint32_t sink_bytes = audio_stream_sample_bytes(&sink->stream) * + samples; + int ret; + + /* process data */ + ret = process(istream, 0, &sink->stream, 0, samples); + + buffer_stream_writeback(sink, sink_bytes); + + comp_update_buffer_produce(sink, sink_bytes); + + return ret; +} diff --git a/src/platform/Kconfig b/src/platform/Kconfig index 80a8f5ccceee..d1c13c88a1eb 100644 --- a/src/platform/Kconfig +++ b/src/platform/Kconfig @@ -9,7 +9,6 @@ choice config TIGERLAKE bool "Build for Tigerlake" - select XT_BOOT_LOADER select XT_IRQ_MAP select DMA_GW select DW @@ -34,6 +33,13 @@ config METEORLAKE help Select if your target platform is Meteorlake-compatible +config LUNARLAKE + bool "Build for Lunarlake" + select ACE + select ACE_VERSION_2_0 + help + Select if your target platform is Lunarlake-compatible + config LIBRARY bool "Build Library" help @@ -125,6 +131,15 @@ config IMX8ULP Select if your target platform is imx8ulp-compatible. imx.8ulp support dsp. +config IMX93_A55 + bool "Build for NXP i.MX93 arm64 architecture (Zephyr-only)" + select BUILD_OUTPUT_BIN + select ZEPHYR_LOG + select HOST_PTABLE + select DMA_DOMAIN + help + Select if your target platform is imx93-compatible. + config RENOIR bool "Build for Renoir" select XT_INTERRUPT_LEVEL_5 @@ -195,6 +210,7 @@ endchoice config MAX_CORE_COUNT int + default 5 if LUNARLAKE default 4 if TIGERLAKE default 3 if METEORLAKE default 1 @@ -272,6 +288,12 @@ config ACE_VERSION_1_5 help Select for ACE version 1.5 +config ACE_VERSION_2_0 + depends on ACE + bool + help + Select for ACE version 2.0 + config HP_MEMORY_BANKS int "HP memory banks count" depends on CAVS @@ -407,6 +429,7 @@ config HAVE_AGENT config AMS bool "Enable Async Messaging Service" default n + depends on IPC_MAJOR_4 help Enables Async Messaging Service. Async messages are used to send messages between modules. diff --git a/src/platform/imx93_a55/CMakeLists.txt b/src/platform/imx93_a55/CMakeLists.txt new file mode 100644 index 000000000000..ec909d60035f --- /dev/null +++ b/src/platform/imx93_a55/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: BSD-3-Clause + +add_subdirectory(lib) + +add_local_sources(sof platform.c) diff --git a/src/platform/imx93_a55/include/platform/drivers/idc.h b/src/platform/imx93_a55/include/platform/drivers/idc.h new file mode 100644 index 000000000000..ae7e99b72852 --- /dev/null +++ b/src/platform/imx93_a55/include/platform/drivers/idc.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifdef __ZEPHYR_RTOS_IDC_H__ + +#ifndef __PLATFORM_DRIVERS_IDC_H__ +#define __PLATFORM_DRIVERS_IDC_H__ + +#include + +/* TODO: remove me if possible */ + +struct idc_msg; + +static inline int idc_send_msg(struct idc_msg *msg, uint32_t mode) +{ + return 0; +} + +#endif /* __PLATFORM_DRIVERS_IDC_H__ */ + +#else + +#error "This file shouldn't be included from outside of Zephyr's rtos/idc.h" + +#endif /* __ZEPHYR_RTOS_IDC_H__ */ diff --git a/src/platform/imx93_a55/include/platform/drivers/interrupt.h b/src/platform/imx93_a55/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..239c4a135b84 --- /dev/null +++ b/src/platform/imx93_a55/include/platform/drivers/interrupt.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +/* TODO: remove me if possible */ + +#endif /* __PLATFORM_DRIVERS_INTERRUPT_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/drivers/interrupt.h" + +#endif /* __SOF_DRIVERS_INTERRUPT_H__ */ diff --git a/src/platform/imx93_a55/include/platform/lib/clk.h b/src/platform/imx93_a55/include/platform/lib/clk.h new file mode 100644 index 000000000000..6703c1304a7a --- /dev/null +++ b/src/platform/imx93_a55/include/platform/lib/clk.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H___ + +#define CLK_CPU(x) (x) +#define CPU_DEFAULT_IDX 0 +#define NUM_CLOCKS 1 +#define NUM_CPU_FREQ 1 + +struct sof; + +void platform_clock_init(struct sof *sof); + +#endif /* __PLATFORM_LIB_CLK_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/clk.h" + +#endif /* __SOF_LIB_CLK_H__ */ diff --git a/src/platform/imx93_a55/include/platform/lib/cpu.h b/src/platform/imx93_a55/include/platform/lib/cpu.h new file mode 100644 index 000000000000..7a92a59b574f --- /dev/null +++ b/src/platform/imx93_a55/include/platform/lib/cpu.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifdef __SOF_LIB_CPU_H__ + +#ifndef __PLATFORM_LIB_CPU_H__ +#define __PLATFORM_LIB_CPU_H__ + +/* note: although the core assigned to the inmate + * might not have the ID = 0 according to Linux, + * Zephyr will still index its cores starting from 0. + */ +#define PLATFORM_PRIMARY_CORE_ID 0 + +#endif /* __PLATFORM_LIB_CPU_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/cpu.h" + +#endif /* __SOF_LIB_CPU_H__ */ diff --git a/src/platform/imx93_a55/include/platform/lib/dai.h b/src/platform/imx93_a55/include/platform/lib/dai.h new file mode 100644 index 000000000000..1fc983ebbeee --- /dev/null +++ b/src/platform/imx93_a55/include/platform/lib/dai.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifdef __SOF_LIB_DAI_H__ + +#ifndef __PLATFORM_LIB_DAI_H__ +#define __PLATFORM_LIB_DAI_H__ + +/* TODO: remove me whenever possible */ + +#endif /* __PLATFORM_LIB_DAI_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/dai.h" + +#endif /* __SOF_LIB_DAI_H__ */ diff --git a/src/platform/imx93_a55/include/platform/lib/dma.h b/src/platform/imx93_a55/include/platform/lib/dma.h new file mode 100644 index 000000000000..93d62c2dec5d --- /dev/null +++ b/src/platform/imx93_a55/include/platform/lib/dma.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifdef __SOF_LIB_DMA_H__ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +/* i.MX93 uses dummy DMA and EDMA */ +#define PLATFORM_NUM_DMACS 2 + +#define DMA_ID_EDMA2 0 +#define DMA_ID_HOST 1 + +/* TODO: this is already defined with EDMA2_CHAN_MAX */ +#define PLATFORM_MAX_DMA_CHAN 64 + +/* TODO: required by Zephyr DMA domain to work */ +#define dma_chan_irq_name(dma, chan) dma_irq_name(dma) +#define dma_chan_irq(dma, chan) ((int *)(dma)->plat_data.drv_plat_data)[chan] + +#endif /* __PLATFORM_LIB_DMA_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/dma.h" + +#endif /* __SOF_LIB_DMA_H__ */ diff --git a/src/platform/imx93_a55/include/platform/lib/mailbox.h b/src/platform/imx93_a55/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..ce3d35d3d5c4 --- /dev/null +++ b/src/platform/imx93_a55/include/platform/lib/mailbox.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +/* i.MX93's mailbox is organized as follows: + * + * +---------------+----------------------+------------------------+-----------+ + * | Region name | Base address | Offset | Size | Permissions | + * +---------------+---------------+--------+---------+------------------------+ + * | Inbox region | 0xce100000 | 0 | 0x1000 | ROOT: R/W, INMATE: R/W | + * +---------------+---------------+--------+---------+------------------------+ + * | Outbox region | 0xce101000 | 0x1000 | 0x1000 | ROOT: R/W, INMATE: R/W | + * +---------------+---------------+--------+---------+------------+-----------+ + * | Stream region | 0xce102000 | 0x2000 | 0x1000 | ROOT: R/W, INMATE: R/W | + * +---------------+---------------+--------+---------+------------------------+ + * + * + * RESTRICTIONS: + * * the inbox region always needs to be placed at offset 0 + * relative to the mailbox memory region used by the Linux host + * driver. Other than that, there's no restrictions regarding the + * placement of these mailbox regions. + * + * Notes: + * * if there's a need to add new regions, simply append the + * new regions to the above table and create memory regions + * inside the Jailhouse configurations for root/inmate cells. + * Also, please make sure that the Linux host driver is also + * aware of these new regions. + * + * * although these regions are placed one after the other please + * note that this isn't a restriction. If there's a need to place + * these regions elsewhere please not that the offset is relative + * to the mailbox memory region used by the Linux host driver. + * + * * TODO: root and inmate shouldn't have the same permissions, fix + * it. + */ + +/* inbox */ +#define MAILBOX_HOSTBOX_SIZE 0x1000 +#define MAILBOX_HOSTBOX_BASE 0xce100000 +#define MAILBOX_HOSTBOX_OFFSET 0 + +/* outbox */ +#define MAILBOX_DSPBOX_SIZE 0x1000 +#define MAILBOX_DSPBOX_BASE 0xce101000 +#define MAILBOX_DSPBOX_OFFSET (MAILBOX_HOSTBOX_OFFSET + MAILBOX_HOSTBOX_SIZE) + +/* stream */ +#define MAILBOX_STREAM_SIZE 0x1000 +#define MAILBOX_STREAM_BASE 0xce102000 +#define MAILBOX_STREAM_OFFSET (MAILBOX_DSPBOX_OFFSET + MAILBOX_DSPBOX_SIZE) + +#endif /* __PLATFORM_LIB_MAILBOX_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/mailbox.h" + +#endif /* __SOF_LIB_MAILBOX_H__ */ diff --git a/src/platform/imx93_a55/include/platform/lib/memory.h b/src/platform/imx93_a55/include/platform/lib/memory.h new file mode 100644 index 000000000000..579c2b43d502 --- /dev/null +++ b/src/platform/imx93_a55/include/platform/lib/memory.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +#include + +#define PLATFORM_DCACHE_ALIGN DCACHE_LINE_SIZE + +/* seems like in xtensa architecture cached data + * may be placed at some special addresses in the + * SRAM? + * + * since we're running on A55 cores, there's no such + * thing so all the below cache/shared data "management" + * functions aren't necessary. + */ +#define SHARED_DATA + +#define uncache_to_cache(address) address +#define cache_to_uncache(address) address +#define cache_to_uncache_init(address) address +#define is_uncached(address) 0 + +/* number of heaps to be used. + * + * i.MX93 is non-SMP so we're only going to use 1 heap. + */ +#define PLATFORM_HEAP_SYSTEM 1 +#define PLATFORM_HEAP_SYSTEM_RUNTIME 1 +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_BUFFER 1 + +/* host and firmware use shared memory */ +#define host_to_local(addr) (addr) +#define local_to_host(addr) (addr) + +/* if this gets too big then it will be + * necessary to increase the SRAM size from + * the Zephyr DTS. This should be fine as + * we're going to reserve 800MB for Jailhouse + * usage. + */ +#define HEAPMEM_SIZE 0x00010000 + +/* SOF uses A side of the WAKEUPMIX MU */ +#define MU_BASE 0x42430000 + +/* SOF uses EDMA2 (a.k.a EDMA4 in the TRM) */ +#define EDMA2_BASE 0x42010000 +#define EDMA2_CHAN_SIZE 0x8000 + +/* WM8962 is connected to SAI3 */ +#define SAI3_BASE 0x42660000 + +static inline void *platform_shared_get(void *ptr, int bytes) +{ + return ptr; +} + +#endif /* __PLATFORM_LIB_MEMORY_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/memory.h" + +#endif /* __SOF_LIB_MEMORY_H__*/ diff --git a/src/platform/imx93_a55/include/platform/lib/pm_runtime.h b/src/platform/imx93_a55/include/platform/lib/pm_runtime.h new file mode 100644 index 000000000000..8665518b08d5 --- /dev/null +++ b/src/platform/imx93_a55/include/platform/lib/pm_runtime.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifdef __SOF_LIB_PM_RUNTIME_H__ + +#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ +#define __PLATFORM_LIB_PM_RUNTIME_H__ + +/* TODO: is this required? Should this be implemented using Zephyr PM + * API? + */ +#include + +struct pm_runtime_data; + +static inline void platform_pm_runtime_init(struct pm_runtime_data *prd) +{ +} + +static inline void platform_pm_runtime_get(uint32_t context, + uint32_t index, + uint32_t flags) +{ +} + +static inline void platform_pm_runtime_put(uint32_t context, + uint32_t index, + uint32_t flags) +{ +} + +static inline void platform_pm_runtime_enable(uint32_t context, + uint32_t index) +{ +} + +static inline void platform_pm_runtime_disable(uint32_t context, + uint32_t index) +{ +} + +static inline bool platform_pm_runtime_is_active(uint32_t context, + uint32_t index) +{ + return false; +} + +#endif /* __PLATFORM_LIB_PM_RUNTIME_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/pm_runtime.h" + +#endif /* __SOF_LIB_PM_RUNTIME_H__ */ diff --git a/src/platform/imx93_a55/include/platform/platform.h b/src/platform/imx93_a55/include/platform/platform.h new file mode 100644 index 000000000000..4811b8015517 --- /dev/null +++ b/src/platform/imx93_a55/include/platform/platform.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#define PLATFORM_DEFAULT_CLOCK CLK_CPU(0) + +/* host uses 4KB page granularity */ +#define HOST_PAGE_SIZE 4096 + +#define PLATFORM_PAGE_TABLE_SIZE 256 + +/* TODO: these values are taken from i.MX8 platform */ +#define PLATFORM_MAX_CHANNELS 4 +#define PLATFORM_MAX_STREAMS 5 + +/* SOF uses A side of the WAKEUPMIX MU. + * We need to add 32 (SPI_BASE) to the + * INTID found in the TRM since all the + * interrupt IDs here are SPIs. + */ +#define PLATFORM_IPC_INTERRUPT (23 + 32) + +#endif /* __PLATFORM_PLATFORM_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/platform.h" + +#endif /* __SOF_PLATFORM_H__ */ diff --git a/src/platform/imx93_a55/include/platform/trace/trace.h b/src/platform/imx93_a55/include/platform/trace/trace.h new file mode 100644 index 000000000000..ab491cf0b7ca --- /dev/null +++ b/src/platform/imx93_a55/include/platform/trace/trace.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +/* TODO: remove me whenever possible */ + +#endif /* __PLATFORM_TRACE_TRACE_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/trace/trace.h" + +#endif /* __SOF_TRACE_TRACE_H__ */ diff --git a/src/platform/imx93_a55/lib/clk.c b/src/platform/imx93_a55/lib/clk.c new file mode 100644 index 000000000000..2fcd3d7814ab --- /dev/null +++ b/src/platform/imx93_a55/lib/clk.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2023 NXP + */ + +#include +#include + +static const struct freq_table platform_cpu_freq[] = { + { CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC, + CONFIG_SYS_CLOCK_TICKS_PER_SEC * 1000 }, +}; + +static struct clock_info platform_clocks_info[NUM_CLOCKS]; + +void platform_clock_init(struct sof *sof) +{ + int i; + + sof->clocks = platform_clocks_info; + + /* The CCM doesn't seem to allow setting a core's + * frequency. It probably sets the whole cluster's + * frequency to some value (not relevant). Since + * we're running on top of Jailhouse we don't want + * to allow SOF to change the cluster's frequency + * since that would also affect Linux. + * + * Also, as a consequence to this, on SMP systems, + * NUM_CLOCKS and CONFIG_CORE_COUNT will probably + * differ so watch out for this when using the below + * code. In the case of i.MX93 this is fince since + * SOF runs on a single core. + */ + for (i = 0; i < CONFIG_CORE_COUNT; i++) { + sof->clocks[i] = (struct clock_info) { + .freqs_num = NUM_CPU_FREQ, + .freqs = platform_cpu_freq, + .default_freq_idx = CPU_DEFAULT_IDX, + .current_freq_idx = CPU_DEFAULT_IDX, + .notification_id = NOTIFIER_ID_CPU_FREQ, + .notification_mask = NOTIFIER_TARGET_CORE_MASK(i), + .set_freq = NULL, + }; + } +} diff --git a/src/platform/imx93_a55/lib/dai.c b/src/platform/imx93_a55/lib/dai.c new file mode 100644 index 000000000000..5f1cb3f7e534 --- /dev/null +++ b/src/platform/imx93_a55/lib/dai.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2023 NXP + */ + +#include +#include +#include +#include + +static struct dai sai[] = { + { + .index = 3, /* SOF uses SAI3 */ + .plat_data = { + .base = SAI3_BASE, + .fifo[SOF_IPC_STREAM_PLAYBACK] = { + .offset = SAI3_BASE + REG_SAI_TDR0, + .depth = 128, /* number of 32-bit words */ + .watermark = 64, /* needs to be half the depth */ + .handshake = EDMA_HANDSHAKE(EDMA2_SAI3_CHAN_TX_IRQ, + EDMA2_SAI3_CHAN_TX, + EDMA2_SAI3_TX_MUX), + }, + .fifo[SOF_IPC_STREAM_CAPTURE] = { + .offset = SAI3_BASE + REG_SAI_RDR0, + .depth = 128, + .watermark = 64, + .handshake = EDMA_HANDSHAKE(EDMA2_SAI3_CHAN_RX_IRQ, + EDMA2_SAI3_CHAN_RX, + EDMA2_SAI3_RX_MUX), + }, + }, + .drv = &sai_driver, + }, +}; + +static const struct dai_type_info dti[] = { + { + .type = SOF_DAI_IMX_SAI, + .dai_array = sai, + .num_dais = ARRAY_SIZE(sai), + }, +}; + +static const struct dai_info lib_dai = { + .dai_type_array = dti, + .num_dai_types = ARRAY_SIZE(dti) +}; + +int dai_init(struct sof *sof) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(sai); i++) + k_spinlock_init(&dti[0].dai_array[i].lock); + + sof->dai_info = &lib_dai; + + return 0; +} diff --git a/src/platform/imx93_a55/lib/dma.c b/src/platform/imx93_a55/lib/dma.c new file mode 100644 index 000000000000..280748711647 --- /dev/null +++ b/src/platform/imx93_a55/lib/dma.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2023 NXP + */ + +#include +#include +#include + +extern struct dma_ops dummy_dma_ops; +extern struct dma_ops edma_ops; + +static const int edma2_ints[EDMA2_CHAN_MAX] = { + [EDMA2_SAI3_CHAN_RX] = EDMA2_SAI3_CHAN_RX_IRQ, + [EDMA2_SAI3_CHAN_TX] = EDMA2_SAI3_CHAN_TX_IRQ, +}; + +static struct dma dma[PLATFORM_NUM_DMACS] = { + { + .plat_data = { + .id = DMA_ID_EDMA2, + .dir = DMA_DIR_MEM_TO_DEV | DMA_DIR_DEV_TO_MEM, + .devs = DMA_DEV_SAI, + .base = EDMA2_BASE, + .chan_size = EDMA2_CHAN_SIZE, + .channels = EDMA2_CHAN_MAX, + .drv_plat_data = edma2_ints, + }, + .ops = &edma_ops, + }, + { + .plat_data = { + .id = DMA_ID_HOST, + .dir = DMA_DIR_HMEM_TO_LMEM | DMA_DIR_LMEM_TO_HMEM, + .devs = DMA_DEV_HOST, + .channels = 16 + }, + .ops = &dummy_dma_ops, + }, +}; + +static const struct dma_info lib_dma = { + .dma_array = dma, + .num_dmas = ARRAY_SIZE(dma) +}; + +int dmac_init(struct sof *sof) +{ + int i; + + /* early lock initialization for ref counting */ + for (i = 0; i < ARRAY_SIZE(dma); i++) + k_spinlock_init(&dma[i].lock); + + sof->dma_info = &lib_dma; + + return 0; +} diff --git a/src/platform/imx93_a55/platform.c b/src/platform/imx93_a55/platform.c new file mode 100644 index 000000000000..b442d5381361 --- /dev/null +++ b/src/platform/imx93_a55/platform.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2023 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const struct sof_ipc_fw_ready ready = { + .hdr = { + .cmd = SOF_IPC_FW_READY, + .size = sizeof(struct sof_ipc_fw_ready), + }, + .version = { + .hdr.size = sizeof(struct sof_ipc_fw_version), + .micro = SOF_MICRO, + .minor = SOF_MINOR, + .major = SOF_MAJOR, + .build = -1, + .date = "dtermin.\0", + .time = "fwready.\0", + .tag = SOF_TAG, + .abi_version = SOF_ABI_VERSION, + .src_hash = SOF_SRC_HASH, + }, + .flags = DEBUG_SET_FW_READY_FLAGS, +}; + +static const struct sof_ipc_window windows = { + .ext_hdr = { + .hdr.cmd = SOF_IPC_FW_READY, + .hdr.size = sizeof(struct sof_ipc_window), + .type = SOF_IPC_EXT_WINDOW, + }, + .num_windows = 3, + .window = { + { + .type = SOF_IPC_REGION_DOWNBOX, + .flags = 0, + .size = MAILBOX_HOSTBOX_SIZE, + .offset = MAILBOX_HOSTBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_UPBOX, + .id = 0, + .flags = 0, + .size = MAILBOX_DSPBOX_SIZE, + .offset = MAILBOX_DSPBOX_OFFSET, + }, + { + .type = SOF_IPC_REGION_STREAM, + .id = 0, + .flags = 0, + .size = MAILBOX_STREAM_SIZE, + .offset = MAILBOX_STREAM_OFFSET, + }, + }, +}; + +int platform_boot_complete(uint32_t boot_message) +{ + struct sof_ipc_reply reply; + + /* prepare reply header */ + reply.error = 0; + reply.hdr.cmd = SOF_IPC_FW_READY; + reply.hdr.size = sizeof(reply); + + /* copy reply header to hostbox */ + mailbox_hostbox_write(0, &reply, sizeof(reply)); + + /* copy firmware ready data to hostbox */ + mailbox_hostbox_write(sizeof(reply), &ready, sizeof(ready)); + + /* write manifest data after firmware ready */ + mailbox_hostbox_write(sizeof(reply) + sizeof(ready), + &windows, + sizeof(windows)); + + /* we can return, the IPC handler will take care of the doorbell */ + return 1; +} + +int platform_context_save(struct sof *sof) +{ + /* TODO: nothing to do here, remove me if possible */ + return 0; +} + +int platform_init(struct sof *sof) +{ + int ret; + + /* Initialize clock data */ + /* TODO: is this really required? */ + platform_clock_init(sof); + + /* Initialize EDF scheduler */ + scheduler_init_edf(); + + /* Initialize Zephyr domain and timer-based scheduler */ + sof->platform_timer_domain = zephyr_domain_init(PLATFORM_DEFAULT_CLOCK); + zephyr_ll_scheduler_init(sof->platform_timer_domain); + + /* Initialize DMAC data */ + ret = dmac_init(sof); + if (ret < 0) + return -ENODEV; + + /* Initialize DMA domain */ + sof->platform_dma_domain = zephyr_dma_domain_init(&sof->dma_info->dma_array[0], + 1, + PLATFORM_DEFAULT_CLOCK); + zephyr_ll_scheduler_init(sof->platform_dma_domain); + + /* Initialize IPC */ + ipc_init(sof); + + /* Initialize DAI */ + dai_init(sof); + + /* We're all set */ + return 0; +} diff --git a/src/platform/intel/ace/include/ace/version.h b/src/platform/intel/ace/include/ace/version.h index 26eb80f053e7..2a5d18ec23a1 100644 --- a/src/platform/intel/ace/include/ace/version.h +++ b/src/platform/intel/ace/include/ace/version.h @@ -9,10 +9,13 @@ #define __ACE_VERSION_H__ #define ACE_VERSION_1_5 0x10500 +#define ACE_VERSION_2_0 0x20000 /* ACE version defined by CONFIG_ACE_VER_ */ #if CONFIG_ACE_VERSION_1_5 #define ACE_VERSION ACE_VERSION_1_5 +#elif CONFIG_ACE_VERSION_2_0 +#define ACE_VERSION ACE_VERSION_2_0 #endif #define HW_CFG_VERSION ACE_VERSION diff --git a/src/platform/intel/ace/platform.c b/src/platform/intel/ace/platform.c index 86afbfa80fef..0fbf364931e2 100644 --- a/src/platform/intel/ace/platform.c +++ b/src/platform/intel/ace/platform.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -74,6 +75,11 @@ int platform_boot_complete(uint32_t boot_message) return ipc_platform_send_msg(&msg); } +static struct pm_notifier pm_state_notifier = { + .state_entry = NULL, + .state_exit = cpu_notify_state_exit, +}; + /* Runs on the primary core only */ int platform_init(struct sof *sof) { @@ -114,6 +120,9 @@ int platform_init(struct sof *sof) if (ret < 0) return ret; + /* register power states entry / exit notifiers */ + pm_notifier_register(&pm_state_notifier); + /* initialize the host IPC mechanisms */ trace_point(TRACE_BOOT_PLATFORM_IPC); ipc_init(sof); diff --git a/src/platform/intel/cavs/CMakeLists.txt b/src/platform/intel/cavs/CMakeLists.txt index 7a026b75b5e1..09b76c325913 100644 --- a/src/platform/intel/cavs/CMakeLists.txt +++ b/src/platform/intel/cavs/CMakeLists.txt @@ -15,23 +15,6 @@ target_link_libraries(sof_static_libraries INTERFACE lps_vector) add_local_sources(sof lps_wait.c) endif() -if(CONFIG_NO_SECONDARY_CORE_ROM) - add_library(altreset STATIC "") - target_link_libraries(altreset sof_options) - target_compile_options(altreset PRIVATE -mtext-section-literals) - - add_local_sources(altreset alternate_reset_vector.S) - - target_link_libraries(sof_static_libraries INTERFACE altreset) -endif() - add_local_sources(sof platform.c) target_include_directories(sof_options INTERFACE ${PROJECT_SOURCE_DIR}/src/platform/intel/cavs/include) - -add_library(cavs_ext_manifest STATIC "") -add_local_sources(cavs_ext_manifest ext_manifest.c) -sof_append_relative_path_definitions(cavs_ext_manifest) - -target_link_libraries(cavs_ext_manifest sof_options) -target_link_libraries(sof_static_libraries INTERFACE cavs_ext_manifest) diff --git a/src/platform/intel/cavs/alternate_reset_vector.S b/src/platform/intel/cavs/alternate_reset_vector.S deleted file mode 100644 index 434b087db1e2..000000000000 --- a/src/platform/intel/cavs/alternate_reset_vector.S +++ /dev/null @@ -1,309 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - */ - - -#include -#include -#include -#if CONFIG_XT_BOOT_LOADER && !CONFIG_VM_ROM -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#include "xtos-internal.h" - -.type secondary_core_init, @function -.type shared_vecbase_ptr, @object - -.section .AlternateResetVector.text, "ax" - - /* Alignemt and padding for 4 dwords is in order to meet - * lpsram header requiremetns */ -_LpsramHeader: - j _AltResetVector - .align 4 - /* Magic value. */ - .long 0 - /* Lp-restore vector address. */ - .long 0 - /* Reserved. */ - .long 0 - - .size _LpsramHeader, . - _LpsramHeader - -.align 4 -_AltResetVectorLiterals: - .literal_position - - .size _AltResetVectorLiterals, . - _AltResetVectorLiterals - -.align 4 -.global _AltResetVector - -.align 4 -_AltResetVector: - movi a0, 0 - movi a1, 1 - wsr a1, WINDOWSTART - wsr a0, WINDOWBASE - rsync - - get_prid a5 - movi a6, PLATFORM_PRIMARY_CORE_ID - bne a5, a6, secondary_init //core0 handle restore, core1 always starts from scratch - /* Currently no implementation for core 0: - - shutoff restore should be put either here on in L1SRAM */ - j alt_boot_error_loop - -secondary_init: - /* Block interrupt but not enable WOE */ - movi a3, PS_UM | PS_INTLEVEL(5) - wsr a3, PS - rsync - - movi a2, 0 - call0 _l1_cache_init - movi a0, 0 - -alt_boot_secondary_core_idc_receiver: - get_prid a5 - movi a3, IPC_DSP_BASE(0) - movi a4, IPC_DSP_SIZE - mull a4, a4, a5 - add a3, a3, a4 - - l32i a2, a3, 0 - bbsi a2, 31, alt_boot_validate_idc_msg - -alt_boot_secondary_core_enter_waiti: - - /* Setup int vector to be local */ - movi a2, _LpsramHeader - wsr a2, vecbase - - get_prid a5 - // Get core interrupt reg - // a5 should still contain processor id - movi a3, IRQ_CPU_OFFSET - mull a3, a3, a5 - movi a2, IRQ_BASE - add a3, a2, a3 - - movi a2, 0xffffffff & ~(BIT(IRQ_BIT_LVL2_IDC)) - s32i a2, a3, 0 - movi a2, 0xffffffff - s32i a2, a3, 0x10 - movi a2, 0xffffffff - s32i a2, a3, 0x20 - movi a2, 0xffffffff - s32i a2, a3, 0x30 - memw // at this point use l32i to read - //Unmask Tensilica L2 interrupt - movi a2, IRQ_MASK_EXT_LEVEL2 - - /* Enable L2 level trigger (external) interrupt */ - movi a2, BIT(6) - wsr a2, INTENABLE - - movi a2, 128 - -alt_boot_secondary_wait_for_waiti: - addi a2, a2, -1 - nop - bnez a2, alt_boot_secondary_wait_for_waiti - -alt_boot_secondary_enter_waiti: - isync - extw - waiti 1 - j alt_boot_secondary_core_idc_receiver - -alt_boot_validate_idc_msg: - /* Core wake version: bits 0-8 (9 - bits) - core wake version must be 0x2. */ - l32i a2, a3, 0 - movi a4, 0x1FF - and a2, a2, a4 - bnei a2, 0x2, alt_boot_handle_incorrect_idc - /* ROM Control Version bits 24-28 (5 bits) - rom control version must be 0x1. */ - l32i a2, a3, 0 - srli a2, a2, 24 - movi a4, 0x1F - and a2, a2, a4 - bnei a2, 0x1, alt_boot_handle_incorrect_idc - - .macro init_vector level - .if GREATERTHAN(XCHAL_NUM_INTLEVELS+1,\level) - .if XCHAL_DEBUGLEVEL-\level - .weak _Level&level&FromVector - movi a4, _Level&level&FromVector - writesr excsave \level a4 - .if GREATERTHAN(\level,XCHAL_EXCM_LEVEL) - movi a5, _Pri_&level&_HandlerAddress - s32i a4, a5, 0 - /* If user provides their own handler, that handler might - * not provide its own _Pri__HandlerAddress variable for - * linking handlers. In that case, the reference below - * would pull in the XTOS handler anyway, causing a conflict. - * To avoid that, provide a weak version of it here: - */ - .pushsection .data, "aw" - .global _Pri_&level&_HandlerAddress - .weak _Pri_&level&_HandlerAddress - .align 4 - _Pri_&level&_HandlerAddress: .space 4 - .popsection - .endif - .endif - .endif - .endm - - -lp_reset_setup_vecbase: - movi a2, shared_vecbase_ptr - l32i a2, a2, 0 - beqz a2, alt_boot_error_loop - /* Apply alternate vector base given from ldscripts. */ - wsr a2, vecbase - - init_vector 2 - init_vector 3 - init_vector 4 - init_vector 5 - -alt_boot_secondary_core_wakeup: - movi a2, 0 - wsr a2, INTENABLE - rsync - - // Compute address to jump - l32i a2, a3, 4 - slli a2, a2, 2 - // Clear busy bit - l32i a4, a3, 0 - s32i a4, a3, 0 - memw - - jx a2 -alt_boot_handle_incorrect_idc: - // Clear BUSY - l32i a2, a3, 0 - s32i a2, a3, 0 - memw - // HW limitation read the register - l32i a4, a3, 0 - j alt_boot_secondary_core_idc_receiver - -alt_boot_error_loop: - // TODO: consider some kind of status reporting here. - j alt_boot_error_loop - - .size _AltResetVector, . - _AltResetVector - -.section .AlternateResetL2IntVector.text, "ax" - -/* Note: at this moment it is essential that this is linked on - * _LpsramHeader + 0x180 */ -.align 4 -.global _AltResetL2IntHandler -_AltResetL2IntHandler: - xsr a2, excsave2 - xor a2, a2, a2 - wsr a2, intenable - xsr a2, excsave2 - rfi 2 - .size _AltResetL2IntHandler, . - _AltResetL2IntHandler - -.section .LpsramCode.text, "ax" - -.literal_position - -.global _l1_cache_init -.align 4 - -_l1_cache_init: - mov a9, a2 - movi a3, CxL1CCFG - bnez a9, l1_cache_enable_one_way - -l1_cache_way_enable_all: - movi a2, L1_CACHE_ALL_WAY_ENABLED_MASK - movi a4, L1_CACHE_ALL_WAY_ACTIVE_MASK - j l1_cache_enable_write - -l1_cache_enable_one_way: - movi a2, L1_CACHE_ONE_WAY_ENABLED_MASK - movi a4, L1_CACHE_ONE_WAY_ACTIVE_MASK - -l1_cache_enable_write: - s32i a2, a3, 0 - -l1_cache_wait_for_way_enable_loop: - l32i a2, a3, 0 - and a2, a2, a4 - bne a2, a4, l1_cache_wait_for_way_enable_loop - -#if XCHAL_HAVE_PREFETCH -l1_cache_pref_ebb_enble: - movi a3, CxL1PCFG - movi a2, L1_CACHE_PREFETCHER_ENABLED - movi a4, L1_CACHE_PREFETCHER_ACTIVE - s32i a2, a3, 0 - -l1_cache_wait_for_prefetcher: - l32i a2, a3, 0 - and a2, a2, a4 - bne a4, a2, l1_cache_wait_for_prefetcher -#endif - -l1_cache_inv_unlock: -#if ! XCHAL_HAVE_ICACHE_DYN_WAYS - icache_reset a2, a3 -#endif - -#if ! XCHAL_HAVE_DCACHE_DYN_WAYS - dcache_reset a2, a3 -#endif - -l1_cache_set_prefctl: -#if XCHAL_HAVE_PREFETCH - /* Enable cache prefetch if present. */ - movi a2, L1_CACHE_PREFCTL_VALUE - wsr a2, PREFCTL -#endif - -l1_cache_setup_memprotection: - movi a2, _memmap_cacheattr_reset - /* NOTE: CLOBBERS a2 - a8 !!! */ - cacheattr_set -#if XCHAL_USE_MEMCTL - bnez a9, l1_cache_init_program_memctl_one_way - -l1_cache_init_program_memctl_all_ways: - movi a3, ((~MEMCTL_SNOOP_EN)) - j l1_cache_init_program_memctl - -l1_cache_init_program_memctl_one_way: - movi a3, ((1 << 8) | (1 << 13) | (1 << 18) | MEMCTL_L0IBUF_EN | 1 << 23) - -l1_cache_init_program_memctl: - wsr a3, MEMCTL - rsync - /* Enable zero-overhead loop instr buffer, and snoop responses, if configured. */ - movi a3, (MEMCTL_SNOOP_EN | MEMCTL_L0IBUF_EN) - rsr a2, MEMCTL - or a2, a2, a3 - wsr a2, MEMCTL - rsync -#endif - ret - - .size _l1_cache_init, . - _l1_cache_init diff --git a/src/platform/intel/cavs/boot_entry.S b/src/platform/intel/cavs/boot_entry.S deleted file mode 100644 index f92cd86f1a44..000000000000 --- a/src/platform/intel/cavs/boot_entry.S +++ /dev/null @@ -1,230 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2016 Intel Corporation. All rights reserved. - * - * Author: Liam Girdwood - */ - -/* - * Entry point from ROM - assumes :- - * - * 1) C runtime environment is initialised by ROM. - * 2) Stack is in first HPSRAM bank. - */ - -#include -#include -#include -#include - -#include -#include -#include "xtos-internal.h" - - .type boot_primary_core, @function - - .begin literal_prefix .boot_entry - .section .boot_entry.text, "ax" - - .align 4 - .global boot_entry - -boot_entry: - entry a1, 48 - j boot_init - - .align 4 - .literal_position -#if defined(PLATFORM_RESET_MHE_AT_BOOT) -l2_mecs: - .word SHIM_L2_MECS -#endif - -#if defined(PLATFORM_DISABLE_L2CACHE_AT_BOOT) -l2_cache_pref: - .word SHIM_L2_PREF_CFG -#endif - -sof_stack_base: - .word __stack - -#if CONFIG_MEM_WND -wnd0_base: - .word DMWBA(0) - -wnd0_size: - .word DMWLO(0) - -wnd0_base_val: - .word HP_SRAM_WIN0_BASE | DMWBA_READONLY | DMWBA_ENABLE - -wnd0_size_val: - .word HP_SRAM_WIN0_SIZE | 0x7 - -wnd0_status_address: - .word HP_SRAM_WIN0_BASE - -wnd0_error_address: - .word HP_SRAM_WIN0_BASE | 0x4 - -fw_loaded_status_value: - .word 0x00000005 - -fw_no_errors_value: - .word 0x00000000 -#endif - -#if defined(PLATFORM_MEM_INIT_AT_BOOT) -shim_ldoctl_address: - .word SHIM_BASE + SHIM_LDOCTL - -ldoctl_hpsram_ldo_on: - .word SHIM_LDOCTL_HPSRAM_LDO_ON - -ldoctl_hpsram_ldo_bypass: - .word SHIM_LDOCTL_HPSRAM_LDO_BYPASS - -hspgctl0_address: - .word HSPGCTL0 - -hsrmctl0_address: - .word HSRMCTL0 - -hspgctl1_address: - .word HSPGCTL1 - -hsrmctl1_address: - .word HSRMCTL1 - -hspgists0_address: - .word HSPGISTS0 - -hspgists1_address: - .word HSPGISTS1 -#endif - -boot_init: - .align 4 -#if defined(PLATFORM_DISABLE_L2CACHE_AT_BOOT) - l32r a3, l2_cache_pref - movi a5, 0 - s32i a5, a3, 0 - memw -#endif - -#if defined(PLATFORM_RESET_MHE_AT_BOOT) - /* reset memory hole */ - l32r a3, l2_mecs - movi a5, 0 - s32i a5, a3, 0 -#endif - -#if defined(PLATFORM_MEM_INIT_AT_BOOT) - /* turn on memory _before_ stack reprogramming */ - - l32r a3, ldoctl_hpsram_ldo_on - l32r a5, shim_ldoctl_address - s32i a3, a5, 0 - memw - - /* delay for 256 iterations before touching pwr regs */ - movi a2, 256 -1: addi.n a2, a2, -1 - bnez a2, 1b - - movi a3, 0 - l32r a5, hspgctl0_address - s32i a3, a5, 0 - memw - - l32r a5, hsrmctl0_address - s32i a3, a5, 0 - memw - - l32r a5, hspgctl1_address - s32i a3, a5, 0 - memw - - l32r a5, hsrmctl1_address - s32i a3, a5, 0 - memw - - /* wait for status of first bank group */ - l32r a5, hspgists0_address -2: - l32i a3, a5, 0 - bnez a3, 2b - - /* wait for status of second bank group */ - l32r a5, hspgists1_address -3: - l32i a3, a5, 0 - bnez a3, 3b - - /* delay for 256 iterations before touching pwr regs */ - movi a2, 256 -4: addi.n a2, a2, -1 - bnez a2, 4b - - l32r a3, ldoctl_hpsram_ldo_bypass - l32r a5, shim_ldoctl_address - s32i a3, a5, 0 - memw -#endif - - /* reprogram stack to the area defined by main FW */ - l32r a3, sof_stack_base - mov sp, a3 - -#if CONFIG_MEM_WND - /* set status register to 0x00000005 in wnd0 */ - l32r a3, fw_loaded_status_value - l32r a5, wnd0_status_address - s32i a3, a5, 0 - - /* set error register to 0x00 in wnd0 */ - l32r a3, fw_no_errors_value - l32r a5, wnd0_error_address - s32i a3, a5, 0 - - /* realloc memory window0 to - continue reporting boot progress */ - l32r a3, wnd0_size - l32r a5, wnd0_size_val - s32i a5, a3, 0 - memw - l32r a3, wnd0_base - l32r a5, wnd0_base_val - s32i a5, a3, 0 - memw -#endif - -#if (XCHAL_DCACHE_IS_COHERENT || XCHAL_LOOP_BUFFER_SIZE) && \ - XCHAL_HW_MIN_VERSION >= XTENSA_HWVERSION_RE_2012_0 - /* Enable zero-overhead loop instr buffer, - and snoop responses, if configured. */ - movi a3, (MEMCTL_SNOOP_EN | MEMCTL_L0IBUF_EN) - rsr a2, MEMCTL - or a2, a2, a3 - wsr a2, MEMCTL -#endif - - /* determine core we are running on */ - get_prid a2 - movi a3, PLATFORM_PRIMARY_CORE_ID - beq a2, a3, 1f - - /* no core should get here */ - j dead - -1: - /* we are primary core so boot it */ - call8 boot_primary_core - -dead: - /* should never get here - we are dead */ - j dead - - .size boot_entry, . - boot_entry - - .end literal_prefix diff --git a/src/platform/intel/cavs/boot_loader.c b/src/platform/intel/cavs/boot_loader.c deleted file mode 100644 index 00828b5eaac4..000000000000 --- a/src/platform/intel/cavs/boot_loader.c +++ /dev/null @@ -1,238 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2016 Intel Corporation. All rights reserved. -// -// Author: Liam Girdwood - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define MANIFEST_BASE IMR_BOOT_LDR_MANIFEST_BASE -#define MANIFEST_SEGMENT_COUNT 3 - -/* generic string compare cloned into the bootloader to - * compact code and make it more readable - */ -int strcmp(const char *s1, const char *s2) -{ - while (*s1 != 0 && *s2 != 0) { - if (*s1 < *s2) - return -1; - if (*s1 > *s2) - return 1; - s1++; - s2++; - } - - /* did both string end */ - if (*s1 != 0) - return 1; - if (*s2 != 0) - return -1; - - /* match */ - return 0; -} - -/* memcopy used by boot loader */ -static inline void bmemcpy(void *dest, void *src, size_t bytes) -{ - uint32_t *d = dest; - uint32_t *s = src; - int i; - - for (i = 0; i < (bytes >> 2); i++) - d[i] = s[i]; - - dcache_writeback_region(dest, bytes); -} - -/* bzero used by bootloader */ -static inline void bbzero(void *dest, size_t bytes) -{ - uint32_t *d = dest; - int i; - - for (i = 0; i < (bytes >> 2); i++) - d[i] = 0; - - dcache_writeback_region(dest, bytes); -} - -static void parse_module(struct sof_man_fw_header *hdr, - struct sof_man_module *mod) -{ - int i; - uint32_t bias; - - /* each module has 3 segments */ - for (i = 0; i < MANIFEST_SEGMENT_COUNT; i++) { - trace_point(TRACE_BOOT_LDR_PARSE_SEGMENT + i); - switch (mod->segment[i].flags.r.type) { - case SOF_MAN_SEGMENT_TEXT: - case SOF_MAN_SEGMENT_DATA: - bias = (mod->segment[i].file_offset - - SOF_MAN_ELF_TEXT_OFFSET); - - /* copy from IMR to SRAM */ - bmemcpy((void *)mod->segment[i].v_base_addr, - (void *)((int)hdr + bias), - mod->segment[i].flags.r.length * - HOST_PAGE_SIZE); - break; - case SOF_MAN_SEGMENT_BSS: - /* copy from IMR to SRAM */ - bbzero((void *)mod->segment[i].v_base_addr, - mod->segment[i].flags.r.length * - HOST_PAGE_SIZE); - break; - default: - /* ignore */ - break; - } - } -} - -/* parse FW manifest and copy modules */ -static void parse_manifest(void) -{ - struct sof_man_fw_desc *desc = - (struct sof_man_fw_desc *)MANIFEST_BASE; - struct sof_man_fw_header *hdr = &desc->header; - struct sof_man_module *mod; - int i; - - /* copy module to SRAM - skip bootloader module */ - for (i = 1; i < hdr->num_module_entries; i++) { - trace_point(TRACE_BOOT_LDR_PARSE_MODULE + i); - mod = (struct sof_man_module *)((char *)desc + - SOF_MAN_MODULE_OFFSET(i)); - parse_module(hdr, mod); - } -} - -#if PLATFORM_MEM_INIT_AT_BOOT - -static uint32_t get_fw_size_in_use(void) -{ - struct sof_man_fw_desc *desc = - (struct sof_man_fw_desc *)MANIFEST_BASE; - struct sof_man_fw_header *hdr = &desc->header; - struct sof_man_module *mod; - uint32_t fw_size_in_use = 0xffffffff; - int i; - - /* Calculate fw size passed in BASEFW module in MANIFEST */ - for (i = 1; i < hdr->num_module_entries; i++) { - trace_point(TRACE_BOOT_LDR_PARSE_MODULE + i); - mod = (struct sof_man_module *)((char *)desc + - SOF_MAN_MODULE_OFFSET(i)); - if (strcmp((char *)mod->name, "BASEFW")) - continue; - for (i = 0; i < MANIFEST_SEGMENT_COUNT; i++) { - if (mod->segment[i].flags.r.type - == SOF_MAN_SEGMENT_BSS) { - fw_size_in_use = mod->segment[i].v_base_addr - - HP_SRAM_BASE - + (mod->segment[i].flags.r.length - * HOST_PAGE_SIZE); - } - } - } - - return fw_size_in_use; -} - -static uint32_t hp_sram_power_memory(uint32_t memory_size, bool enable) -{ - uint32_t start_bank; - uint32_t end_bank; - uint32_t ebb_in_use; - - /* calculate total number of used SRAM banks (EBB) - * to power up only necessary banks - */ - ebb_in_use = SOF_DIV_ROUND_UP(memory_size, SRAM_BANK_SIZE); - - start_bank = enable ? 0 : ebb_in_use; - end_bank = (enable ? ebb_in_use : PLATFORM_HPSRAM_EBB_COUNT) - 1; - - cavs_pm_memory_hp_sram_banks_power_gate(start_bank, end_bank, enable); - - return 0; -} - -static int32_t hp_sram_power_off_unused_banks(uint32_t memory_size) -{ - /* keep enabled only memory banks used by FW */ - return hp_sram_power_memory(memory_size, false); -} - -static int32_t hp_sram_init(void) -{ - return hp_sram_power_memory(HP_SRAM_SIZE, true); -} - -#endif - -/* boot primary core */ -void boot_primary_core(void) -{ -#if PLATFORM_MEM_INIT_AT_BOOT - int32_t result; -#endif - - trace_point(TRACE_BOOT_LDR_ENTRY); - -#if PLATFORM_MEM_INIT_AT_BOOT - /* init the HPSRAM */ - trace_point(TRACE_BOOT_LDR_HPSRAM); - result = hp_sram_init(); - if (result < 0) { - platform_panic(SOF_IPC_PANIC_MEM); - return; - } -#endif - -#if CONFIG_LP_SRAM - /* init the LPSRAM */ - trace_point(TRACE_BOOT_LDR_LPSRAM); - - cavs_pm_memory_lp_sram_banks_power_gate(0, - PLATFORM_LPSRAM_EBB_COUNT - 1, - true); -#endif - -#if CONFIG_L1_DRAM - /* Power ON L1 DRAM memory */ - trace_point(TRACE_BOOT_LDR_L1DRAM); - cavs_pm_memory_l1_dram_banks_power_gate(CONFIG_L1_DRAM_MEMORY_BANKS - 1, - 0, true); -#endif - - /* parse manifest and copy modules */ - trace_point(TRACE_BOOT_LDR_MANIFEST); - parse_manifest(); - -#if PLATFORM_MEM_INIT_AT_BOOT - hp_sram_power_off_unused_banks(get_fw_size_in_use()); -#endif - - /* now call SOF entry */ - trace_point(TRACE_BOOT_LDR_JUMP); - _ResetVector(); -} diff --git a/src/platform/intel/cavs/ext_manifest.c b/src/platform/intel/cavs/ext_manifest.c deleted file mode 100644 index 50309a734770..000000000000 --- a/src/platform/intel/cavs/ext_manifest.c +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -// -// Copyright(c) 2020 Intel Corporation. All rights reserved. -// -// Author: Adrian Bonislawski -// - -#include -#include -#include -#include - -/* Describes elements counter from ext_man_cavs_config dictionary */ -#define CAVS_CONFIG_ELEM_CNT (EXT_MAN_CAVS_CONFIG_LAST_ELEM - 1) - -const struct ext_man_cavs_config_data ext_man_cavs_config - __aligned(EXT_MAN_ALIGN) __section(".fw_metadata") = { - .hdr.type = EXT_MAN_ELEM_PLATFORM_CONFIG_DATA, - .hdr.elem_size = ALIGN_UP_COMPILE(sizeof(struct ext_man_cavs_config_data) + - sizeof(struct config_elem) * CAVS_CONFIG_ELEM_CNT, - EXT_MAN_ALIGN), - .elems = { - {EXT_MAN_CAVS_CONFIG_LPRO, IS_ENABLED(CONFIG_CAVS_LPRO_ONLY)}, - {EXT_MAN_CAVS_CONFIG_OUTBOX_SIZE, SRAM_OUTBOX_SIZE}, - {EXT_MAN_CAVS_CONFIG_INBOX_SIZE, SRAM_INBOX_SIZE}, - }, -}; diff --git a/src/platform/intel/cavs/lps_pic_restore_vector.S b/src/platform/intel/cavs/lps_pic_restore_vector.S deleted file mode 100644 index 42da750c710b..000000000000 --- a/src/platform/intel/cavs/lps_pic_restore_vector.S +++ /dev/null @@ -1,108 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2019 Intel Corporation. All rights reserved. - * - * Author: Marcin Maka - */ - -#include -#include -#include -#include - -#define MEMCTL_INIT_BIT 23 -#define MEMCTL_INIT_VAL (MEMCTL_L0IBUF_EN | 1 << MEMCTL_INIT_BIT) -#define SW_INT_NUM 7 -#define SW_INT_MASK (1< + +#endif /* __PLATFORM_DRIVERS_IDC_H__ */ + +#else + +#error "This file shouldn't be included from outside of Zephyr/XTOS's rtos/idc.h" + +#endif diff --git a/src/platform/lunarlake/include/platform/drivers/interrupt.h b/src/platform/lunarlake/include/platform/drivers/interrupt.h new file mode 100644 index 000000000000..49f654efaae9 --- /dev/null +++ b/src/platform/lunarlake/include/platform/drivers/interrupt.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + * Rander Wang + */ + +#ifdef __SOF_DRIVERS_INTERRUPT_H__ + +#ifndef __PLATFORM_DRIVERS_INTERRUPT_H__ +#define __PLATFORM_DRIVERS_INTERRUPT_H__ + +#if !defined(__ASSEMBLER__) && !defined(LINKER) + +#include + +#include + +#endif + +/* Required by sof/drivers/interrupt.h */ +#define PLATFORM_IRQ_CHILDREN 32 + +/* Required by zephyr/wrapper.c */ +#define IRQ_NUM_EXT_LEVEL2 4 /* level 2 */ +#define IRQ_NUM_EXT_LEVEL5 16 /* level 5 */ + +#endif /* __PLATFORM_DRIVERS_INTERRUPT_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/drivers/interrupt.h" + +#endif /* __SOF_DRIVERS_INTERRUPT_H__ */ diff --git a/src/platform/lunarlake/include/platform/lib/clk.h b/src/platform/lunarlake/include/platform/lib/clk.h new file mode 100644 index 000000000000..fe8f140ff0a6 --- /dev/null +++ b/src/platform/lunarlake/include/platform/lib/clk.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + * Rander Wang + */ + +#ifdef __SOF_LIB_CLK_H__ + +#ifndef __PLATFORM_LIB_CLK_H__ +#define __PLATFORM_LIB_CLK_H__ + +#include + +#define CLK_MAX_CPU_HZ 400000000 + +#define CPU_WOVCRO_FREQ_IDX 0 + +#define CPU_LPRO_FREQ_IDX 1 + +#define CPU_HPRO_FREQ_IDX 2 + +#define CPU_LOWEST_FREQ_IDX CPU_WOVCRO_FREQ_IDX + +#define CPU_DEFAULT_IDX CPU_HPRO_FREQ_IDX + +#define SSP_DEFAULT_IDX 1 + +#define NUM_CPU_FREQ 3 + +#define NUM_SSP_FREQ 3 + +#endif /* __PLATFORM_LIB_CLK_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/clk.h" + +#endif /* __SOF_LIB_CLK_H__ */ diff --git a/src/platform/lunarlake/include/platform/lib/cpu.h b/src/platform/lunarlake/include/platform/lib/cpu.h new file mode 100644 index 000000000000..5abe9a99d57e --- /dev/null +++ b/src/platform/lunarlake/include/platform/lib/cpu.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +/** + * \file + * \brief DSP core parameters. + */ + +#ifdef __SOF_LIB_CPU_H__ + +#ifndef __PLATFORM_LIB_CPU_H__ +#define __PLATFORM_LIB_CPU_H__ + +#include + +#endif /* __PLATFORM_LIB_CPU_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/cpu.h" + +#endif /* __SOF_LIB_CPU_H__ */ diff --git a/src/platform/lunarlake/include/platform/lib/dai.h b/src/platform/lunarlake/include/platform/lib/dai.h new file mode 100644 index 000000000000..3d52e0bc20bf --- /dev/null +++ b/src/platform/lunarlake/include/platform/lib/dai.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Jaroslaw Stelter + */ + +#ifdef __SOF_LIB_DAI_H__ + +#ifndef __PLATFORM_LIB_DAI_H__ +#define __PLATFORM_LIB_DAI_H__ + +/* SSP */ + +/* + * Number of base and extended SSP ports must be defined separately + * since some HW registers are in two groups, one for base and one + * for extended. + */ + +/** \brief Number of 'base' SSP ports available */ +#define DAI_NUM_SSP_BASE 3 + +/* HD/A */ + +/** \brief Number of HD/A Link Outputs */ +#define DAI_NUM_HDA_OUT 9 + +/** \brief Number of HD/A Link Inputs */ +#define DAI_NUM_HDA_IN 11 + +/* ALH */ + +/** \brief Number of ALH bi-directional links */ +#define DAI_NUM_ALH_BI_DIR_LINKS 0 + +/** \brief Number of contiguous ALH bi-dir links */ +#define DAI_NUM_ALH_BI_DIR_LINKS_GROUP 0 + +#endif /* __PLATFORM_LIB_DAI_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/dai.h" + +#endif /* __SOF_LIB_DAI_H__ */ diff --git a/src/platform/lunarlake/include/platform/lib/dma.h b/src/platform/lunarlake/include/platform/lib/dma.h new file mode 100644 index 000000000000..c820f6e2c9e9 --- /dev/null +++ b/src/platform/lunarlake/include/platform/lib/dma.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifdef __SOF_LIB_DMA_H__ + +#ifndef __PLATFORM_LIB_DMA_H__ +#define __PLATFORM_LIB_DMA_H__ + +/* max number of supported DMA channels */ +#define PLATFORM_MAX_DMA_CHAN 11 + +#endif /* __PLATFORM_LIB_DMA_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/dma.h" + +#endif /* __SOF_LIB_DMA_H__ */ diff --git a/src/platform/lunarlake/include/platform/lib/mailbox.h b/src/platform/lunarlake/include/platform/lib/mailbox.h new file mode 100644 index 000000000000..f559d31d911d --- /dev/null +++ b/src/platform/lunarlake/include/platform/lib/mailbox.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifdef __SOF_LIB_MAILBOX_H__ + +#ifndef __PLATFORM_LIB_MAILBOX_H__ +#define __PLATFORM_LIB_MAILBOX_H__ + +#include + +#endif /* __PLATFORM_LIB_MAILBOX_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/mailbox.h" + +#endif /* __SOF_LIB_MAILBOX_H__ */ diff --git a/src/platform/lunarlake/include/platform/lib/memory.h b/src/platform/lunarlake/include/platform/lib/memory.h new file mode 100644 index 000000000000..5f7ced26f922 --- /dev/null +++ b/src/platform/lunarlake/include/platform/lib/memory.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Marcin Rajwa + */ + +#ifdef __SOF_LIB_MEMORY_H__ + +#ifndef __PLATFORM_LIB_MEMORY_H__ +#define __PLATFORM_LIB_MEMORY_H__ + +/* prioritize definitions in Zephyr SoC layer */ +#ifdef __ZEPHYR__ +#include +#endif + +#include +#include +#include + +/* HP SRAM windows */ +#define WIN_BASE(n) DT_REG_ADDR(DT_PHANDLE(MEM_WINDOW_NODE(n), memory)) + +/* window 0 */ +#define SRAM_SW_REG_BASE ((uint32_t)(WIN_BASE(0) + WIN0_OFFSET)) +#define SRAM_SW_REG_SIZE 0x1000 + +#define SRAM_OUTBOX_BASE (SRAM_SW_REG_BASE + SRAM_SW_REG_SIZE) +#define SRAM_OUTBOX_SIZE 0x1000 + +/* window 1 */ +#define SRAM_INBOX_BASE ((uint32_t)(WIN_BASE(1) + WIN1_OFFSET)) +#define SRAM_INBOX_SIZE ((uint32_t)WIN_SIZE(1)) + +/* window 2 */ +#define SRAM_DEBUG_BASE ((uint32_t)(WIN_BASE(2) + WIN2_OFFSET)) +#define SRAM_DEBUG_SIZE 0x800 + +#define SRAM_EXCEPT_BASE (SRAM_DEBUG_BASE + SRAM_DEBUG_SIZE) +#define SRAM_EXCEPT_SIZE 0x800 + +#define SRAM_STREAM_BASE (SRAM_EXCEPT_BASE + SRAM_EXCEPT_SIZE) +#define SRAM_STREAM_SIZE 0x1000 + +/* Stack configuration */ +#define SOF_STACK_SIZE 0x1000 + +#define PLATFORM_HEAP_SYSTEM CONFIG_CORE_COUNT /* one per core */ +#define PLATFORM_HEAP_SYSTEM_RUNTIME CONFIG_CORE_COUNT /* one per core */ +#define PLATFORM_HEAP_RUNTIME 1 +#define PLATFORM_HEAP_RUNTIME_SHARED 1 +#define PLATFORM_HEAP_SYSTEM_SHARED 1 +#define PLATFORM_HEAP_BUFFER 2 + +/** + * size of HPSRAM system heap + */ +#define HEAPMEM_SIZE 0x40000 + +#endif /* __PLATFORM_LIB_MEMORY_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/memory.h" + +#endif /* __SOF_LIB_MEMORY_H__ */ diff --git a/src/platform/lunarlake/include/platform/lib/pm_runtime.h b/src/platform/lunarlake/include/platform/lib/pm_runtime.h new file mode 100644 index 000000000000..a5d16dc40f78 --- /dev/null +++ b/src/platform/lunarlake/include/platform/lib/pm_runtime.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Tomasz Lauda + */ + +/** + * \file platform/lunarlake/include/platform/lib/pm_runtime.h + * \brief Runtime power management header file for Tigerlake + * \author Tomasz Lauda + */ + +#ifdef __SOF_LIB_PM_RUNTIME_H__ + +#ifndef __PLATFORM_LIB_PM_RUNTIME_H__ +#define __PLATFORM_LIB_PM_RUNTIME_H__ + +#include +#include + +/** + * \brief extra pwr flag to power up a core with a specific reason + * it can be powered down only with the same reason (flag) + */ +#define PWRD_MASK MASK(31, 30) +#define PWRD_BY_HPRO BIT(31) /**< requested by HPRO */ +#define PWRD_BY_TPLG BIT(30) /**< typical power up */ + +struct pm_runtime_data; + +/** + * \brief Initializes platform specific runtime power management. + * \param[in,out] prd Runtime power management data. + */ +void platform_pm_runtime_init(struct pm_runtime_data *prd); + +/** + * \brief Retrieves platform specific power management resource. + * + * \param[in] context - Type of power management context. + * \param[in] index - index of the device. + * \param[in] flags - Flags, set of RPM_... + */ +void platform_pm_runtime_get(uint32_t context, uint32_t index, uint32_t flags); + +/** + * \brief Releases platform specific power management resource. + * + * \param[in] context - Type of power management context. + * \param[in] index - Index of the device. + * \param[in] flags - Flags, set of RPM_... + */ +void platform_pm_runtime_put(uint32_t context, uint32_t index, uint32_t flags); + +void platform_pm_runtime_prepare_d0ix_en(uint32_t index); + +void platform_pm_runtime_enable(uint32_t context, uint32_t index); + +void platform_pm_runtime_disable(uint32_t context, uint32_t index); + +bool platform_pm_runtime_is_active(uint32_t context, uint32_t index); + +void platform_pm_runtime_power_off(void); + +#endif /* __PLATFORM_LIB_PM_RUNTIME_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/pm_runtime.h" + +#endif /* __SOF_LIB_PM_RUNTIME_H__ */ diff --git a/src/platform/lunarlake/include/platform/lib/shim.h b/src/platform/lunarlake/include/platform/lib/shim.h new file mode 100644 index 000000000000..8b5e2817cfd2 --- /dev/null +++ b/src/platform/lunarlake/include/platform/lib/shim.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + * Rander Wang + */ + +#ifdef __SOF_LIB_SHIM_H__ + +#ifndef __PLATFORM_LIB_SHIM_H__ +#define __PLATFORM_LIB_SHIM_H__ + +#include +#include + +/** \brief Request HP RING Oscillator Clock */ +#define SHIM_CLKCTL_RHROSCC BIT(31) + +/** \brief Request WOVCRO Clock */ +#define SHIM_CLKCTL_WOV_CRO_REQUEST BIT(4) + +/** \brief Request LP RING Oscillator Clock */ +#define SHIM_CLKCTL_RLROSCC BIT(29) + +/** \brief Oscillator Clock Select*/ +#define SHIM_CLKCTL_OCS_HP_RING BIT(2) +#define SHIM_CLKCTL_OCS_LP_RING 0 +#define SHIM_CLKCTL_WOVCROSC BIT(3) + +/** \brief LP Memory Clock Select */ +#define SHIM_CLKCTL_LMCS_DIV4 BIT(1) + +/** \brief HP Memory Clock Select */ +#define SHIM_CLKCTL_HMCS_DIV2 0 + +/** \brief HP RING Oscillator Clock Status */ +#define SHIM_CLKSTS_HROSCCS BIT(31) + +/** \brief WOVCRO Clock Status */ +#define SHIM_CLKSTS_WOV_CRO BIT(4) + +/** \brief LP RING Oscillator Clock Status */ +#define SHIM_CLKSTS_LROSCCS BIT(29) + +#define L2HSBPM(x) (0x17A800 + 0x0008 * (x)) +#define SHIM_HSPGCTL(x) (L2HSBPM(x) + 0x0000) + +#define LSPGCTL 0x71D80 + +#endif /* __PLATFORM_LIB_SHIM_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/lib/shim.h" + +#endif /* __SOF_LIB_SHIM_H__ */ diff --git a/src/platform/lunarlake/include/platform/platform.h b/src/platform/lunarlake/include/platform/platform.h new file mode 100644 index 000000000000..38e379ae31f4 --- /dev/null +++ b/src/platform/lunarlake/include/platform/platform.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + * + * Author: Liam Girdwood + * Keyon Jie + * Rander Wang + * Xiuli Pan + */ + +#ifdef __SOF_PLATFORM_H__ + +#ifndef __PLATFORM_PLATFORM_H__ +#define __PLATFORM_PLATFORM_H__ + +#include + +/*! \def PLATFORM_DEFAULT_CLOCK + * \brief clock source for audio pipeline + * + * There are two types of clock: cpu clock which is a internal clock in + * xtensa core, and ssp clock which is provided by external HW IP. + * The choice depends on HW features on different platform + */ +#define PLATFORM_DEFAULT_CLOCK CLK_SSP + +/* Host page size */ +#define HOST_PAGE_SIZE 4096 + +/* Platform stream capabilities */ +#define PLATFORM_MAX_CHANNELS 8 +#define PLATFORM_MAX_STREAMS 16 + +/* local buffer size of DMA tracing */ +#define DMA_TRACE_LOCAL_SIZE (HOST_PAGE_SIZE * 2) + +/* DSP default delay in cycles */ +#define PLATFORM_DEFAULT_DELAY 12 + +#endif /* __PLATFORM_PLATFORM_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/platform.h" + +#endif /* __SOF_PLATFORM_H__ */ diff --git a/src/platform/lunarlake/include/platform/trace/trace.h b/src/platform/lunarlake/include/platform/trace/trace.h new file mode 100644 index 000000000000..ee9170adc6a0 --- /dev/null +++ b/src/platform/lunarlake/include/platform/trace/trace.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2023 Intel Corporation. All rights reserved. + */ + +#ifdef __SOF_TRACE_TRACE_H__ + +#ifndef __PLATFORM_TRACE_TRACE_H__ +#define __PLATFORM_TRACE_TRACE_H__ + +#include +#include +#include +#include + +/* Platform defined trace code */ +static inline void platform_trace_point(uint32_t x) +{ } + +#endif /* __PLATFORM_TRACE_TRACE_H__ */ + +#else + +#error "This file shouldn't be included from outside of sof/trace/trace.h" + +#endif /* __SOF_TRACE_TRACE_H__ */ diff --git a/src/platform/lunarlake/lib/clk.c b/src/platform/lunarlake/lib/clk.c new file mode 100644 index 000000000000..ed2936b5efc4 --- /dev/null +++ b/src/platform/lunarlake/lib/clk.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2023 Intel Corporation. All rights reserved. +// +// Author: Tomasz Lauda +// Janusz Jankowski + +#include +#include + +static const struct freq_table platform_cpu_freq[] = { + { 38400000, 38400 }, + { 120000000, 120000 }, + { CLK_MAX_CPU_HZ, 400000 }, +}; + +STATIC_ASSERT(ARRAY_SIZE(platform_cpu_freq) == NUM_CPU_FREQ, invalid_number_of_cpu_frequencies); + +const struct freq_table *cpu_freq = platform_cpu_freq; diff --git a/src/platform/posix/include/platform/drivers/alh.h b/src/platform/posix/include/platform/drivers/alh.h new file mode 100644 index 000000000000..c53613144dfd --- /dev/null +++ b/src/platform/posix/include/platform/drivers/alh.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2023 Google LLC. All rights reserved. + * Author: Andy Ross + */ +/* empty file, must be included but defines no needed APIs */ + diff --git a/src/platform/posix/include/platform/lib/clk.h b/src/platform/posix/include/platform/lib/clk.h index 2e17b20bdb7d..3c9ff3b96950 100644 --- a/src/platform/posix/include/platform/lib/clk.h +++ b/src/platform/posix/include/platform/lib/clk.h @@ -2,3 +2,12 @@ * Copyright(c) 2022 Google LLC. All rights reserved. * Author: Andy Ross */ + +#define CLK_MAX_CPU_HZ CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC +#define CPU_LPRO_FREQ_IDX 1 + +/* This is not a platform function, it's defined in src/lib/clk.c. + * But the declaration has historically been in the platform layer, so + * it's repeated here. + */ +uint32_t clock_get_freq(int clock); diff --git a/src/platform/posix/include/platform/lib/dai.h b/src/platform/posix/include/platform/lib/dai.h index 2e17b20bdb7d..02b58fb55681 100644 --- a/src/platform/posix/include/platform/lib/dai.h +++ b/src/platform/posix/include/platform/lib/dai.h @@ -2,3 +2,10 @@ * Copyright(c) 2022 Google LLC. All rights reserved. * Author: Andy Ross */ + +#define DAI_NUM_ALH_BI_DIR_LINKS_GROUP 4 +#define DAI_NUM_HDA_IN 10 +#define DAI_NUM_HDA_OUT 9 +#define DAI_NUM_SSP_BASE 6 +#define DAI_NUM_ALH_BI_DIR_LINKS 16 + diff --git a/src/platform/posix/include/platform/lib/mailbox.h b/src/platform/posix/include/platform/lib/mailbox.h index 376e3c319bba..3a42e93f6ea2 100644 --- a/src/platform/posix/include/platform/lib/mailbox.h +++ b/src/platform/posix/include/platform/lib/mailbox.h @@ -7,4 +7,22 @@ #include +static inline uint32_t mailbox_sw_reg_read(size_t offset) +{ + return 0; +} + +static inline uint64_t mailbox_sw_reg_read64(size_t offset) +{ + return 0; +} + +static inline void mailbox_sw_reg_write(size_t offset, uint32_t src) +{ +} + +static inline void mailbox_sw_regs_write(size_t offset, const void *src, size_t bytes) +{ +} + #endif /* PLATFORM_POSIX_LIB_MAILBOX_H */ diff --git a/src/platform/posix/include/platform/lib/memory.h b/src/platform/posix/include/platform/lib/memory.h index 50ea8ffc091e..1118cda6c8d0 100644 --- a/src/platform/posix/include/platform/lib/memory.h +++ b/src/platform/posix/include/platform/lib/memory.h @@ -39,6 +39,11 @@ static inline void *platform_shared_get(void *ptr, int bytes) return ptr; } +#define SRAM_BANK_SIZE 0x10000 +#define EBB_BANKS_IN_SEGMENT 32 +#define PLATFORM_HPSRAM_EBB_COUNT 32 +#define PLATFORM_LPSRAM_EBB_COUNT 1 + #define SHARED_DATA /**/ #endif /* PLATFORM_HOST_PLATFORM_MEMORY_H */ diff --git a/src/platform/posix/include/platform/platform.h b/src/platform/posix/include/platform/platform.h index 5c9c264d54e5..aae9ac4be4f9 100644 --- a/src/platform/posix/include/platform/platform.h +++ b/src/platform/posix/include/platform/platform.h @@ -24,6 +24,8 @@ #define PLATFORM_DEFAULT_DELAY 12 +#define HW_CFG_VERSION 0x010000 + struct sof; void posix_dma_init(struct sof *sof); diff --git a/src/platform/posix/ipc.c b/src/platform/posix/ipc.c index 8a1f800cb158..d5dbcf09e040 100644 --- a/src/platform/posix/ipc.c +++ b/src/platform/posix/ipc.c @@ -69,6 +69,7 @@ static void fuzz_isr(const void *arg) memmove(&fuzz_in[0], &fuzz_in[n + 1], rem); fuzz_in_sz = rem; +#ifdef CONFIG_IPC_MAJOR_3 // One special case: a first byte of 0xff (which is in the // otherwise-ignored size value at the front of the command -- // we rewrite those) is interpreted as a "component new" @@ -129,32 +130,48 @@ static void fuzz_isr(const void *arg) struct comp_driver_info *di = drvs[comp_idx % ndrvs]; memcpy(cmd->ext.uuid, di->drv->uid, sizeof(cmd->ext.uuid)); } +#endif posix_ipc_isr(NULL); } -// This API is a little confounded by its history. The job of this -// function is to get a newly-received IPC message header (!) into the -// comp_data buffer on the IPC object, the rest of the message -// (including the header!) into the mailbox region (obviously on Intel -// that's a shared memory region where data was already written by the -// host kernel) and then call ipc_cmd() with the same pointer. With -// IPC3, this copy is done inside mailbox_validate(). +// This API is... confounded by its history. With IPC3, the job of +// this function is to get a newly-received IPC message header (!) +// into the comp_data buffer on the IPC object, the rest of the +// message (including the header!) into the mailbox region (obviously +// on Intel that's a shared memory region where data was already +// written by the host kernel) and then call ipc_cmd() with the same +// pointer. With IPC3, this copy is done inside mailbox_validate(). // -// On IPC4 all of this is a noop and the platform is responsible for -// what memory to use and what pointer to pass to ipc_cmd(). We do -// this compatibly by starting with the message in comp_data and -// copying it into the hostbox unconditionally. +// On IPC4, the header is copied out by calling +// ipc_compact_read_msg(), which then calls back into our code via +// ipc_platform_compact_read_msg(), writing 8 bytes unconditionally on +// the header object it receives, which is then returned here, and +// then passed to ipc_cmd(). enum task_state ipc_platform_do_cmd(struct ipc *ipc) { struct ipc_cmd_hdr *hdr; +#ifdef CONFIG_IPC_MAJOR_4 + hdr = ipc_compact_read_msg(); +#else memcpy(posix_hostbox, global_ipc->comp_data, SOF_IPC_MSG_MAX_SIZE); hdr = mailbox_validate(); +#endif + ipc_cmd(hdr); return SOF_TASK_STATE_COMPLETED; } +int ipc_platform_compact_read_msg(struct ipc_cmd_hdr *hdr, int words) +{ + if (words != 2) + return 0; + + memcpy(hdr, global_ipc->comp_data, 8); + return 2; +} + // Re-raise the interrupt if there's still fuzz data to process void ipc_platform_complete_cmd(struct ipc *ipc) { @@ -168,11 +185,22 @@ void ipc_platform_complete_cmd(struct ipc *ipc) int ipc_platform_send_msg(const struct ipc_msg *msg) { + // IPC4 will send zero-length messages with a null buffer + // pointer, which otherwise gets detected as an error by + // memcpy_s underneath mailbox_dspbox_write() + if (IS_ENABLED(CONFIG_IPC_MAJOR_4) && msg->tx_size == 0) + return 0; + // There is no host, just write to the mailbox to validate the buffer mailbox_dspbox_write(0, msg->tx_data, msg->tx_size); return 0; } +void ipc_platform_send_msg_direct(const struct ipc_msg *msg) +{ + /* TODO: add support */ +} + int platform_ipc_init(struct ipc *ipc) { IRQ_CONNECT(CONFIG_ARCH_POSIX_FUZZ_IRQ, 0, fuzz_isr, NULL, 0); diff --git a/src/probe/probe.c b/src/probe/probe.c index f80e3eceb231..8a9704e700c2 100644 --- a/src/probe/probe.c +++ b/src/probe/probe.c @@ -829,9 +829,9 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) } if (_probe->probe_points[i].purpose == PROBE_PURPOSE_EXTRACTION) { - format = probe_gen_format(buffer->stream.frame_fmt, - buffer->stream.rate, - buffer->stream.channels); + format = probe_gen_format(audio_stream_get_frm_fmt(&buffer->stream), + audio_stream_get_rate(&buffer->stream), + audio_stream_get_channels(&buffer->stream)); ret = probe_gen_header(buffer_id, cb_data->transaction_amount, format, &checksum); @@ -840,9 +840,9 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) /* check if transaction amount exceeds component buffer end addr */ /* if yes: divide copying into two stages, head and tail */ - if ((char *)cb_data->transaction_begin_address + - cb_data->transaction_amount > (char *)buffer->stream.end_addr) { - head = (uintptr_t)buffer->stream.end_addr - + if ((char *)cb_data->transaction_begin_address + cb_data->transaction_amount > + (char *)audio_stream_get_end_addr(&buffer->stream)) { + head = (uintptr_t)audio_stream_get_end_addr(&buffer->stream) - (uintptr_t)cb_data->transaction_begin_address; tail = (uintptr_t)cb_data->transaction_amount - head; ret = copy_to_pbuffer(&_probe->ext_dma.dmapb, @@ -852,7 +852,7 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) goto err; ret = copy_to_pbuffer(&_probe->ext_dma.dmapb, - buffer->stream.addr, tail); + audio_stream_get_addr(&buffer->stream), tail); if (ret < 0) goto err; } else { @@ -896,9 +896,9 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) /* check if transaction amount exceeds component buffer end addr */ /* if yes: divide copying into two stages, head and tail */ - if ((char *)cb_data->transaction_begin_address + - cb_data->transaction_amount > (char *)buffer->stream.end_addr) { - head = (char *)buffer->stream.end_addr - + if ((char *)cb_data->transaction_begin_address + cb_data->transaction_amount > + (char *)audio_stream_get_end_addr(&buffer->stream)) { + head = (char *)audio_stream_get_end_addr(&buffer->stream) - (char *)cb_data->transaction_begin_address; tail = cb_data->transaction_amount - head; @@ -908,7 +908,7 @@ static void probe_cb_produce(void *arg, enum notify_id type, void *data) goto err; ret = copy_from_pbuffer(&dma->dmapb, - buffer->stream.addr, tail); + audio_stream_get_addr(&buffer->stream), tail); if (ret < 0) goto err; } else { diff --git a/src/samples/audio/CMakeLists.txt b/src/samples/audio/CMakeLists.txt index 51bc3f5d1023..328070c2bb52 100644 --- a/src/samples/audio/CMakeLists.txt +++ b/src/samples/audio/CMakeLists.txt @@ -1,9 +1,14 @@ # SPDX-License-Identifier: BSD-3-Clause - if(CONFIG_SAMPLE_SMART_AMP) - add_local_sources(sof - smart_amp_test.c - ) + if(CONFIG_IPC_MAJOR_3) + add_local_sources(sof + smart_amp_test_ipc3.c + ) + elseif(CONFIG_IPC_MAJOR_4) + add_local_sources(sof + smart_amp_test_ipc4.c + ) + endif() endif() if(CONFIG_SAMPLE_KEYPHRASE) diff --git a/src/samples/audio/detect_test.c b/src/samples/audio/detect_test.c index 58c218824228..5c6903e07794 100644 --- a/src/samples/audio/detect_test.c +++ b/src/samples/audio/detect_test.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -41,6 +40,13 @@ #include #include #include +#if CONFIG_AMS +#include +#include +#include +#else +#include +#endif #define ACTIVATION_DEFAULT_SHIFT 3 #define ACTIVATION_DEFAULT_COEF 0.05 @@ -85,7 +91,6 @@ struct comp_data { uint32_t keyphrase_samples; /**< keyphrase length in samples */ uint32_t drain_req; /** defines draining size in bytes. */ uint16_t sample_valid_bytes; - struct kpb_event_data event_data; struct kpb_client client_data; #if CONFIG_KWD_NN_SAMPLE_KEYPHRASE @@ -98,6 +103,12 @@ struct comp_data { void (*detect_func)(struct comp_dev *dev, const struct audio_stream __sparse_cache *source, uint32_t frames); struct sof_ipc_comp_event event; + +#if CONFIG_AMS + uint32_t kpd_uuid_id; +#else + struct kpb_event_data event_data; +#endif /* CONFIG_AMS */ }; static inline bool detector_is_sample_width_supported(enum sof_ipc_frame sf) @@ -140,6 +151,31 @@ static void notify_host(const struct comp_dev *dev) #endif /* CONFIG_IPC_MAJOR_4 */ } +#if CONFIG_AMS + +/* Key-phrase detected message*/ +static const ams_uuid_t ams_kpd_msg_uuid = AMS_KPD_MSG_UUID; + +static int ams_notify_kpb(const struct comp_dev *dev) +{ + struct comp_data *cd = comp_get_drvdata(dev); + struct ams_message_payload ams_payload; + + cd->client_data.r_ptr = NULL; + cd->client_data.sink = NULL; + cd->client_data.id = 0; /**< TODO: acquire proper id from kpb */ + /* time in milliseconds */ + cd->client_data.drain_req = (cd->drain_req != 0) ? + cd->drain_req : + cd->config.drain_req; + + ams_helper_prepare_payload(dev, &ams_payload, cd->kpd_uuid_id, + (uint8_t *)&cd->client_data, + sizeof(struct kpb_client)); + + return ams_send(&ams_payload); +} +#else static void notify_kpb(const struct comp_dev *dev) { struct comp_data *cd = comp_get_drvdata(dev); @@ -160,11 +196,16 @@ static void notify_kpb(const struct comp_dev *dev) NOTIFIER_TARGET_CORE_ALL_MASK, &cd->event_data, sizeof(cd->event_data)); } +#endif /* CONFIG_AMS */ void detect_test_notify(const struct comp_dev *dev) { notify_host(dev); +#if CONFIG_AMS + ams_notify_kpb(dev); +#else notify_kpb(dev); +#endif } static void default_detect_test(struct comp_dev *dev, @@ -284,7 +325,7 @@ static void test_keyword_set_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { struct comp_data *cd = comp_get_drvdata(dev); - uint32_t __sparse_cache valid_fmt, frame_fmt; + enum sof_ipc_frame valid_fmt, frame_fmt; comp_info(dev, "test_keyword_set_params()"); @@ -719,6 +760,15 @@ static void test_keyword_free(struct comp_dev *dev) comp_info(dev, "test_keyword_free()"); +#if CONFIG_AMS + int ret; + + /* Unregister KD as AMS producer */ + ret = ams_helper_unregister_producer(dev, cd->kpd_uuid_id); + if (ret) + comp_err(dev, "test_keyword_free(): unregister ams error %d", ret); +#endif + ipc_msg_free(cd->msg); comp_data_blob_handler_free(cd->model_handler); rfree(cd); @@ -766,9 +816,9 @@ static int test_keyword_params(struct comp_dev *dev, sourceb = list_first_item(&dev->bsource_list, struct comp_buffer, sink_list); source_c = buffer_acquire(sourceb); - channels = source_c->stream.channels; - frame_fmt = source_c->stream.frame_fmt; - rate = source_c->stream.rate; + channels = audio_stream_get_channels(&source_c->stream); + frame_fmt = audio_stream_get_frm_fmt(&source_c->stream); + rate = audio_stream_get_rate(&source_c->stream); buffer_release(source_c); if (channels != 1) { @@ -796,6 +846,10 @@ static int test_keyword_params(struct comp_dev *dev, return err; } +#if CONFIG_AMS + cd->kpd_uuid_id = AMS_INVALID_MSG_TYPE; +#endif /* CONFIG_AMS */ + cd->config.activation_threshold = err; return 0; @@ -837,7 +891,7 @@ static int test_keyword_copy(struct comp_dev *dev) struct comp_buffer, sink_list); source_c = buffer_acquire(source); - if (!source_c->stream.avail) { + if (!audio_stream_get_avail(&source_c->stream)) { buffer_release(source_c); return PPL_STATUS_PATH_STOP; } @@ -874,6 +928,7 @@ static int test_keyword_prepare(struct comp_dev *dev) struct comp_data *cd = comp_get_drvdata(dev); uint16_t valid_bits = cd->sample_valid_bytes * 8; uint16_t sample_width; + int ret; #if CONFIG_IPC_MAJOR_4 sample_width = cd->base_cfg.audio_fmt.depth; @@ -887,7 +942,7 @@ static int test_keyword_prepare(struct comp_dev *dev) /* Default threshold value has to be changed * according to host new format. */ - int ret = test_keyword_get_threshold(dev, valid_bits); + ret = test_keyword_get_threshold(dev, valid_bits); if (ret < 0) { comp_err(dev, "test_keyword_prepare(): unsupported sample width %u", @@ -902,6 +957,14 @@ static int test_keyword_prepare(struct comp_dev *dev) &cd->data_blob_size, &cd->data_blob_crc); +#if CONFIG_AMS + /* Register KD as AMS producer */ + ret = ams_helper_register_producer(dev, &cd->kpd_uuid_id, + ams_kpd_msg_uuid); + if (ret) + return ret; +#endif + return comp_set_state(dev, COMP_TRIGGER_PREPARE); } diff --git a/src/samples/audio/smart_amp_test.c b/src/samples/audio/smart_amp_test_ipc3.c similarity index 64% rename from src/samples/audio/smart_amp_test.c rename to src/samples/audio/smart_amp_test_ipc3.c index 10eb2e6f31e2..a8c9e0898dde 100644 --- a/src/samples/audio/smart_amp_test.c +++ b/src/samples/audio/smart_amp_test_ipc3.c @@ -16,10 +16,6 @@ #include #endif -#if CONFIG_IPC_MAJOR_4 -#include -#endif - static const struct comp_driver comp_smart_amp; LOG_MODULE_REGISTER(smart_amp_test, CONFIG_SOF_LOG_LEVEL); @@ -31,10 +27,12 @@ DECLARE_SOF_RT_UUID("smart_amp-test", smart_amp_comp_uuid, 0x167a961e, 0x8ae4, DECLARE_TR_CTX(smart_amp_comp_tr, SOF_UUID(smart_amp_comp_uuid), LOG_LEVEL_INFO); +typedef int(*smart_amp_proc)(struct comp_dev *dev, + const struct audio_stream __sparse_cache *source, + const struct audio_stream __sparse_cache *sink, uint32_t frames, + int8_t *chan_map); + struct smart_amp_data { -#if CONFIG_IPC_MAJOR_4 - struct sof_smart_amp_ipc4_config ipc4_cfg; -#endif struct sof_smart_amp_config config; struct comp_data_blob_handler *model_handler; void *data_blob; @@ -44,8 +42,6 @@ struct smart_amp_data { struct comp_buffer *feedback_buf; /**< feedback source buffer */ struct comp_buffer *sink_buf; /**< sink buffer */ - struct k_mutex lock; /**< protect feedback_buf updated */ - smart_amp_proc process; uint32_t in_channels; @@ -56,12 +52,8 @@ static struct comp_dev *smart_amp_new(const struct comp_driver *drv, const struct comp_ipc_config *config, const void *spec) { -#if CONFIG_IPC_MAJOR_3 const struct ipc_config_process *ipc_sa = spec; const struct sof_smart_amp_config *cfg; -#else - const struct ipc4_base_module_extended_cfg *base_cfg = spec; -#endif struct smart_amp_data *sad; struct comp_dev *dev; size_t bs; @@ -82,35 +74,14 @@ static struct comp_dev *smart_amp_new(const struct comp_driver *drv, if (!sad->model_handler) goto sad_fail; - k_mutex_init(&sad->lock); - -#if CONFIG_IPC_MAJOR_4 - if (base_cfg->base_cfg_ext.nb_input_pins != SMART_AMP_NUM_IN_PINS || - base_cfg->base_cfg_ext.nb_output_pins != SMART_AMP_NUM_OUT_PINS) { - comp_err(dev, "smart_amp_new(): Invalid pin configuration"); - goto sad_fail; - } - - /* Copy the base_cfg */ - memcpy_s(&sad->ipc4_cfg.base, sizeof(sad->ipc4_cfg.base), - &base_cfg->base_cfg, sizeof(base_cfg->base_cfg)); - /* Copy the pin formats */ - bs = sizeof(sad->ipc4_cfg.input_pins) + sizeof(sad->ipc4_cfg.output_pin); - memcpy_s(sad->ipc4_cfg.input_pins, bs, - base_cfg->base_cfg_ext.pin_formats, bs); -#else cfg = (struct sof_smart_amp_config *)ipc_sa->data; bs = ipc_sa->size; - - if ((bs > 0) && (bs < sizeof(struct sof_smart_amp_config))) { + if (bs > 0 && bs < sizeof(struct sof_smart_amp_config)) { comp_err(dev, "smart_amp_new(): failed to apply config"); goto sad_fail; } - memcpy_s(&sad->config, sizeof(struct sof_smart_amp_config), cfg, bs); -#endif - dev->state = COMP_STATE_READY; return dev; @@ -123,196 +94,10 @@ static struct comp_dev *smart_amp_new(const struct comp_driver *drv, return NULL; } -#if CONFIG_IPC_MAJOR_4 -static void smart_amp_set_params(struct comp_dev *dev, - struct sof_ipc_stream_params *params) -{ - struct smart_amp_data *sad = comp_get_drvdata(dev); - struct comp_buffer *sink; - struct comp_buffer __sparse_cache *sink_c; - - comp_dbg(dev, "smart_amp_set_params()"); - - memset(params, 0, sizeof(*params)); - params->channels = sad->ipc4_cfg.base.audio_fmt.channels_count; - params->rate = sad->ipc4_cfg.base.audio_fmt.sampling_frequency; - params->sample_container_bytes = sad->ipc4_cfg.base.audio_fmt.depth / 8; - params->sample_valid_bytes = - sad->ipc4_cfg.base.audio_fmt.valid_bit_depth / 8; - params->buffer_fmt = sad->ipc4_cfg.base.audio_fmt.interleaving_style; - params->buffer.size = sad->ipc4_cfg.base.ibs; - - /* update sink format */ - if (!list_is_empty(&dev->bsink_list)) { - struct ipc4_output_pin_format *sink_fmt = &sad->ipc4_cfg.output_pin; - struct ipc4_audio_format out_fmt = sink_fmt->audio_fmt; - - sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); - sink_c = buffer_acquire(sink); - sink_c->stream.channels = out_fmt.channels_count; - sink_c->stream.rate = out_fmt.sampling_frequency; - - audio_stream_fmt_conversion(out_fmt.depth, - out_fmt.valid_bit_depth, - &sink_c->stream.frame_fmt, - &sink_c->stream.valid_sample_fmt, - out_fmt.s_type); - - sink_c->buffer_fmt = out_fmt.interleaving_style; - params->frame_fmt = sink_c->stream.frame_fmt; - - sink_c->hw_params_configured = true; - - buffer_release(sink_c); - } -} - -static inline int smart_amp_set_config(struct comp_dev *dev, const char *data, - uint32_t data_size) -{ - struct smart_amp_data *sad = comp_get_drvdata(dev); - struct sof_smart_amp_config *cfg; - uint32_t cfg_size; - - cfg = (struct sof_smart_amp_config *)data; - cfg_size = data_size; - - if (cfg_size != sizeof(struct sof_smart_amp_config)) { - comp_err(dev, "smart_amp_set_config(): invalid config size %u, expect %u", - cfg_size, sizeof(struct sof_smart_amp_config)); - return -EINVAL; - } - - comp_dbg(dev, "smart_amp_set_config(): config size = %u", cfg_size); - - memcpy_s(&sad->config, sizeof(struct sof_smart_amp_config), cfg, - sizeof(struct sof_smart_amp_config)); - - return 0; -} - -static inline int smart_amp_get_config(struct comp_dev *dev, char *data, - uint32_t *data_size) -{ - struct smart_amp_data *sad = comp_get_drvdata(dev); - uint32_t cfg_size; - - cfg_size = sizeof(struct sof_smart_amp_config); - - if (cfg_size > *data_size) { - comp_err(dev, "smart_amp_get_config(): wrong config size %d", - *data_size); - } - - *data_size = cfg_size; - - return memcpy_s(data, cfg_size, &sad->config, cfg_size); -} - -static int smart_amp_set_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, - bool last_block, uint32_t data_offset, const char *data) -{ - struct smart_amp_data *sad = comp_get_drvdata(dev); - - comp_dbg(dev, "smart_amp_set_large_config()"); - - switch (param_id) { - case SMART_AMP_SET_MODEL: - return ipc4_comp_data_blob_set(sad->model_handler, - first_block, - last_block, - data_offset, - data); - case SMART_AMP_SET_CONFIG: - return smart_amp_set_config(dev, data, data_offset); - default: - return -EINVAL; - } -} - -static int smart_amp_get_large_config(struct comp_dev *dev, uint32_t param_id, bool first_block, - bool last_block, uint32_t *data_offset, char *data) -{ - comp_dbg(dev, "smart_amp_get_large_config()"); - - switch (param_id) { - case SMART_AMP_GET_CONFIG: - return smart_amp_get_config(dev, data, data_offset); - default: - return -EINVAL; - } -} - -static int smart_amp_get_attribute(struct comp_dev *dev, uint32_t type, - void *value) -{ - struct smart_amp_data *sad = comp_get_drvdata(dev); - - comp_dbg(dev, "smart_amp_get_attribute()"); - - switch (type) { - case COMP_ATTR_BASE_CONFIG: - *(struct ipc4_base_module_cfg *)value = sad->ipc4_cfg.base; - return 0; - default: - return -EINVAL; - } -} - -static int smart_amp_bind(struct comp_dev *dev, void *data) -{ - struct smart_amp_data *sad = comp_get_drvdata(dev); - struct comp_buffer __sparse_cache *buffer_c; - struct comp_buffer *source_buffer; - struct list_item *blist; - - comp_dbg(dev, "smart_amp_bind()"); - - /* searching for feedback source buffers */ - list_for_item(blist, &dev->bsource_list) { - source_buffer = container_of(blist, struct comp_buffer, sink_list); - - k_mutex_lock(&sad->lock, K_FOREVER); - buffer_c = buffer_acquire(source_buffer); - if (IPC4_SINK_QUEUE_ID(buffer_c->id) == SOF_SMART_AMP_FEEDBACK_QUEUE_ID) { - sad->feedback_buf = source_buffer; - buffer_c->stream.channels = sad->config.feedback_channels; - buffer_c->stream.rate = sad->ipc4_cfg.base.audio_fmt.sampling_frequency; - - buffer_release(buffer_c); - k_mutex_unlock(&sad->lock); - break; - } - - buffer_release(buffer_c); - k_mutex_unlock(&sad->lock); - } - - return 0; -} - -static int smart_amp_unbind(struct comp_dev *dev, void *data) -{ - struct smart_amp_data *sad = comp_get_drvdata(dev); - struct ipc4_module_bind_unbind *bu = data; - - comp_dbg(dev, "smart_amp_unbind()"); - - if (bu->extension.r.dst_queue == SOF_SMART_AMP_FEEDBACK_QUEUE_ID) { - k_mutex_lock(&sad->lock, K_FOREVER); - sad->feedback_buf = NULL; - k_mutex_unlock(&sad->lock); - } - - return 0; -} - -#else - static void smart_amp_set_params(struct comp_dev *dev, struct sof_ipc_stream_params *params) { - //nothing to do + /* nothing to do */ } static int smart_amp_set_config(struct comp_dev *dev, @@ -347,9 +132,9 @@ static int smart_amp_get_config(struct comp_dev *dev, { struct smart_amp_data *sad = comp_get_drvdata(dev); size_t bs; - int ret = 0; + int ret; - // Copy back to user space + /* Copy back to user space */ bs = sad->config.size; comp_dbg(dev, "smart_amp_set_config(), actual blob size = %u, expected blob size = %u", @@ -372,49 +157,40 @@ static int smart_amp_ctrl_get_bin_data(struct comp_dev *dev, int size) { struct smart_amp_data *sad = comp_get_drvdata(dev); - int ret = 0; assert(sad); switch (cdata->data->type) { case SOF_SMART_AMP_CONFIG: - ret = smart_amp_get_config(dev, cdata, size); - break; + return smart_amp_get_config(dev, cdata, size); case SOF_SMART_AMP_MODEL: - ret = comp_data_blob_get_cmd(sad->model_handler, cdata, size); - break; + return comp_data_blob_get_cmd(sad->model_handler, cdata, size); default: - comp_err(dev, "smart_amp_ctrl_get_bin_data(): unknown binary data type"); + comp_warn(dev, "smart_amp_ctrl_get_bin_data(): unknown binary data type"); break; } - return ret; + return 0; } static int smart_amp_ctrl_get_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata, int size) { - int ret = 0; - comp_info(dev, "smart_amp_ctrl_get_data() size: %d", size); switch (cdata->cmd) { case SOF_CTRL_CMD_BINARY: - ret = smart_amp_ctrl_get_bin_data(dev, cdata, size); - break; + return smart_amp_ctrl_get_bin_data(dev, cdata, size); default: comp_err(dev, "smart_amp_ctrl_get_data(): invalid cdata->cmd"); return -EINVAL; } - - return ret; } static int smart_amp_ctrl_set_bin_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) { struct smart_amp_data *sad = comp_get_drvdata(dev); - int ret = 0; assert(sad); @@ -425,24 +201,20 @@ static int smart_amp_ctrl_set_bin_data(struct comp_dev *dev, switch (cdata->data->type) { case SOF_SMART_AMP_CONFIG: - ret = smart_amp_set_config(dev, cdata); - break; + return smart_amp_set_config(dev, cdata); case SOF_SMART_AMP_MODEL: - ret = comp_data_blob_set_cmd(sad->model_handler, cdata); - break; + return comp_data_blob_set_cmd(sad->model_handler, cdata); default: - comp_err(dev, "smart_amp_ctrl_set_bin_data(): unknown binary data type"); + comp_warn(dev, "smart_amp_ctrl_set_bin_data(): unknown binary data type"); break; } - return ret; + return 0; } static int smart_amp_ctrl_set_data(struct comp_dev *dev, struct sof_ipc_ctrl_data *cdata) { - int ret = 0; - /* Check version from ABI header */ if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { comp_err(dev, "smart_amp_ctrl_set_data(): invalid version"); @@ -455,15 +227,13 @@ static int smart_amp_ctrl_set_data(struct comp_dev *dev, break; case SOF_CTRL_CMD_BINARY: comp_info(dev, "smart_amp_ctrl_set_data(), SOF_CTRL_CMD_BINARY"); - ret = smart_amp_ctrl_set_bin_data(dev, cdata); - break; + return smart_amp_ctrl_set_bin_data(dev, cdata); default: comp_err(dev, "smart_amp_ctrl_set_data(): invalid cdata->cmd"); - ret = -EINVAL; - break; + return -EINVAL; } - return ret; + return 0; } /* used to pass standard and bespoke commands (with data) to component */ @@ -484,8 +254,6 @@ static int smart_amp_cmd(struct comp_dev *dev, int cmd, void *data, } } -#endif /* CONFIG_IPC_MAJOR_4 */ - static void smart_amp_free(struct comp_dev *dev) { struct smart_amp_data *sad = comp_get_drvdata(dev); @@ -526,7 +294,7 @@ static int smart_amp_params(struct comp_dev *dev, err = smart_amp_verify_params(dev, params); if (err < 0) { comp_err(dev, "smart_amp_params(): pcm params verification failed."); - return -EINVAL; + return err; } return 0; @@ -542,18 +310,16 @@ static int smart_amp_trigger(struct comp_dev *dev, int cmd) ret = comp_set_state(dev, cmd); if (ret == COMP_STATUS_STATE_ALREADY_SET) - ret = PPL_STATUS_PATH_STOP; + return PPL_STATUS_PATH_STOP; switch (cmd) { case COMP_TRIGGER_START: case COMP_TRIGGER_RELEASE: - k_mutex_lock(&sad->lock, K_FOREVER); if (sad->feedback_buf) { struct comp_buffer __sparse_cache *buf = buffer_acquire(sad->feedback_buf); buffer_zero(buf); buffer_release(buf); } - k_mutex_unlock(&sad->lock); break; case COMP_TRIGGER_PAUSE: case COMP_TRIGGER_STOP: @@ -592,7 +358,7 @@ static int smart_amp_process_s16(struct comp_dev *dev, } out_frag++; } - in_frag += source->channels; + in_frag += audio_stream_get_channels(source); } return 0; } @@ -624,7 +390,7 @@ static int smart_amp_process_s32(struct comp_dev *dev, } out_frag++; } - in_frag += source->channels; + in_frag += audio_stream_get_channels(source); } return 0; @@ -633,7 +399,7 @@ static int smart_amp_process_s32(struct comp_dev *dev, static smart_amp_proc get_smart_amp_process(struct comp_dev *dev, struct comp_buffer __sparse_cache *buf) { - switch (buf->stream.frame_fmt) { + switch (audio_stream_get_frm_fmt(&buf->stream)) { case SOF_IPC_FRAME_S16_LE: return smart_amp_process_s16; case SOF_IPC_FRAME_S24_4LE: @@ -664,7 +430,6 @@ static int smart_amp_copy(struct comp_dev *dev) audio_stream_avail_frames(&source_buf->stream, &sink_buf->stream); - k_mutex_lock(&sad->lock, K_FOREVER); if (sad->feedback_buf) { struct comp_buffer __sparse_cache *buf = buffer_acquire(sad->feedback_buf); @@ -692,7 +457,6 @@ static int smart_amp_copy(struct comp_dev *dev) buffer_release(buf); } - k_mutex_unlock(&sad->lock); if (!avail_frames) avail_frames = avail_passthrough_frames; @@ -751,12 +515,10 @@ static int smart_amp_prepare(struct comp_dev *dev) sink_list); buffer_c = buffer_acquire(source_buffer); -#if CONFIG_IPC_MAJOR_3 /* FIXME: how often can this loop be run? */ if (buffer_c->source->ipc_config.type == SOF_COMP_DEMUX) sad->feedback_buf = source_buffer; else -#endif sad->source_buf = source_buffer; buffer_release(buffer_c); @@ -766,21 +528,19 @@ static int smart_amp_prepare(struct comp_dev *dev) source_list); buffer_c = buffer_acquire(sad->sink_buf); - sad->out_channels = buffer_c->stream.channels; + sad->out_channels = audio_stream_get_channels(&buffer_c->stream); buffer_release(buffer_c); buffer_c = buffer_acquire(sad->source_buf); - sad->in_channels = buffer_c->stream.channels; + sad->in_channels = audio_stream_get_channels(&buffer_c->stream); - k_mutex_lock(&sad->lock, K_FOREVER); if (sad->feedback_buf) { struct comp_buffer __sparse_cache *buf = buffer_acquire(sad->feedback_buf); buf->stream.channels = sad->config.feedback_channels; - buf->stream.rate = buffer_c->stream.rate; + buf->stream.rate = audio_stream_get_rate(&buffer_c->stream); buffer_release(buf); } - k_mutex_unlock(&sad->lock); sad->process = get_smart_amp_process(dev, buffer_c); if (!sad->process) { @@ -802,15 +562,7 @@ static const struct comp_driver comp_smart_amp = { .free = smart_amp_free, .params = smart_amp_params, .prepare = smart_amp_prepare, -#if CONFIG_IPC_MAJOR_4 - .set_large_config = smart_amp_set_large_config, - .get_large_config = smart_amp_get_large_config, - .get_attribute = smart_amp_get_attribute, - .bind = smart_amp_bind, - .unbind = smart_amp_unbind, -#else .cmd = smart_amp_cmd, -#endif /* CONFIG_IPC_MAJOR_4 */ .trigger = smart_amp_trigger, .copy = smart_amp_copy, .reset = smart_amp_reset, diff --git a/src/samples/audio/smart_amp_test_ipc4.c b/src/samples/audio/smart_amp_test_ipc4.c new file mode 100644 index 000000000000..8e116445dc8e --- /dev/null +++ b/src/samples/audio/smart_amp_test_ipc4.c @@ -0,0 +1,421 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2020 Intel Corporation. All rights reserved. +// +// Author: Bartosz Kokoszko +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __ZEPHYR__ +#include +#endif +#include + +LOG_MODULE_REGISTER(smart_amp_test, CONFIG_SOF_LOG_LEVEL); + +/* 167a961e-8ae4-11ea-89f1-000c29ce1635 */ +DECLARE_SOF_RT_UUID("smart_amp-test", smart_amp_comp_uuid, 0x167a961e, 0x8ae4, + 0x11ea, 0x89, 0xf1, 0x00, 0x0c, 0x29, 0xce, 0x16, 0x35); + +DECLARE_TR_CTX(smart_amp_comp_tr, SOF_UUID(smart_amp_comp_uuid), + LOG_LEVEL_INFO); +typedef int(*smart_amp_proc)(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, uint32_t frames, + int8_t *chan_map); +struct smart_amp_data { + struct sof_smart_amp_ipc4_config ipc4_cfg; + struct sof_smart_amp_config config; + struct comp_data_blob_handler *model_handler; + void *data_blob; + size_t data_blob_size; + smart_amp_proc process; + uint32_t out_channels; +}; + +static int smart_amp_init(struct processing_module *mod) +{ + struct smart_amp_data *sad; + struct comp_dev *dev = mod->dev; + struct module_data *mod_data = &mod->priv; + const size_t in_size = sizeof(struct ipc4_input_pin_format) * SMART_AMP_NUM_IN_PINS; + const size_t out_size = sizeof(struct ipc4_output_pin_format) * SMART_AMP_NUM_OUT_PINS; + int ret; + const struct ipc4_base_module_extended_cfg *base_cfg = mod_data->cfg.init_data; + + comp_dbg(dev, "smart_amp_init()"); + sad = rzalloc(SOF_MEM_ZONE_RUNTIME, 0, SOF_MEM_CAPS_RAM, sizeof(*sad)); + if (!sad) + return -ENOMEM; + + mod_data->private = sad; + + /* component model data handler */ + sad->model_handler = comp_data_blob_handler_new(dev); + if (!sad->model_handler) { + ret = -ENOMEM; + goto sad_fail; + } + + if (base_cfg->base_cfg_ext.nb_input_pins != SMART_AMP_NUM_IN_PINS || + base_cfg->base_cfg_ext.nb_output_pins != SMART_AMP_NUM_OUT_PINS) { + comp_err(dev, "smart_amp_init(): Invalid pin configuration"); + ret = -EINVAL; + goto sad_fail; + } + + /* Copy the pin formats */ + memcpy_s(sad->ipc4_cfg.input_pins, in_size, + base_cfg->base_cfg_ext.pin_formats, in_size); + memcpy_s(&sad->ipc4_cfg.output_pin, out_size, + &base_cfg->base_cfg_ext.pin_formats[in_size], out_size); + + mod->simple_copy = true; + + return 0; + +sad_fail: + comp_data_blob_handler_free(sad->model_handler); + rfree(sad); + return ret; +} + +static void smart_amp_set_params(struct processing_module *mod) +{ + const struct ipc4_audio_format *audio_fmt = &mod->priv.cfg.base_cfg.audio_fmt; + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_dev *dev = mod->dev; + struct smart_amp_data *sad = module_get_private_data(mod); + struct comp_buffer *sink; + struct comp_buffer __sparse_cache *sink_c; + enum sof_ipc_frame frame_fmt, valid_fmt; + int i; + + memset(params, 0, sizeof(*params)); + params->channels = audio_fmt->channels_count; + params->rate = audio_fmt->sampling_frequency; + params->sample_container_bytes = audio_fmt->depth / 8; + params->sample_valid_bytes = audio_fmt->valid_bit_depth / 8; + params->buffer_fmt = audio_fmt->interleaving_style; + params->buffer.size = mod->priv.cfg.base_cfg.ibs; + + for (i = 0; i < SOF_IPC_MAX_CHANNELS; i++) + params->chmap[i] = (audio_fmt->ch_map >> i * 4) & 0xf; + + /* update sink format */ + if (!list_is_empty(&dev->bsink_list)) { + struct ipc4_output_pin_format *sink_fmt = &sad->ipc4_cfg.output_pin; + struct ipc4_audio_format out_fmt = sink_fmt->audio_fmt; + + sink = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); + sink_c = buffer_acquire(sink); + + audio_stream_fmt_conversion(out_fmt.depth, + out_fmt.valid_bit_depth, + &frame_fmt, &valid_fmt, + out_fmt.s_type); + + audio_stream_set_frm_fmt(&sink_c->stream, frame_fmt); + audio_stream_set_valid_fmt(&sink_c->stream, valid_fmt); + audio_stream_set_channels(&sink_c->stream, out_fmt.channels_count); + audio_stream_set_rate(&sink_c->stream, out_fmt.sampling_frequency); + sink_c->buffer_fmt = out_fmt.interleaving_style; + params->frame_fmt = audio_stream_get_frm_fmt(&sink_c->stream); + sink_c->hw_params_configured = true; + buffer_release(sink_c); + } +} + +static int smart_amp_set_config(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) +{ + struct comp_dev *dev = mod->dev; + struct smart_amp_data *sad = module_get_private_data(mod); + + comp_dbg(dev, "smart_amp_set_config()"); + + switch (config_id) { + case SMART_AMP_SET_MODEL: + return comp_data_blob_set(sad->model_handler, pos, + data_offset_size, fragment, fragment_size); + case SMART_AMP_SET_CONFIG: + if (fragment_size != sizeof(sad->config)) { + comp_err(dev, "smart_amp_set_config(): invalid config size %u, expect %u", + fragment_size, sizeof(struct sof_smart_amp_config)); + return -EINVAL; + } + comp_dbg(dev, "smart_amp_set_config(): config size = %u", fragment_size); + memcpy_s(&sad->config, sizeof(sad->config), fragment, fragment_size); + return 0; + default: + return -EINVAL; + } +} + +static inline int smart_amp_get_config(struct processing_module *mod, + uint32_t config_id, uint32_t *data_offset_size, + uint8_t *fragment, size_t fragment_size) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + int ret; + + comp_dbg(dev, "smart_amp_get_config()"); + + switch (config_id) { + case SMART_AMP_GET_CONFIG: + ret = memcpy_s(fragment, fragment_size, &sad->config, sizeof(sad->config)); + if (ret) { + comp_err(dev, "smart_amp_get_config(): wrong config size %d", + fragment_size); + return ret; + } + *data_offset_size = sizeof(sad->config); + return 0; + default: + return -EINVAL; + } +} + +static int smart_amp_free(struct processing_module *mod) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "smart_amp_free()"); + comp_data_blob_handler_free(sad->model_handler); + rfree(sad); + return 0; +} + +static int smart_amp_params(struct processing_module *mod) +{ + struct sof_ipc_stream_params *params = mod->stream_params; + struct comp_dev *dev = mod->dev; + int ret; + + comp_dbg(dev, "smart_amp_params()"); + smart_amp_set_params(mod); + ret = comp_verify_params(dev, BUFF_PARAMS_CHANNELS, params); + if (ret < 0) { + comp_err(dev, "smart_amp_params(): pcm params verification failed."); + return -EINVAL; + } + return 0; +} + +static int smart_amp_process_s16(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, + uint32_t frames, int8_t *chan_map) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct audio_stream __sparse_cache *source = bsource->data; + struct audio_stream __sparse_cache *sink = bsink->data; + int16_t *src; + int16_t *dest; + uint32_t in_frag = 0; + uint32_t out_frag = 0; + int i; + int j; + + bsource->consumed += frames * source->channels * sizeof(int16_t); + for (i = 0; i < frames; i++) { + for (j = 0 ; j < sad->out_channels; j++) { + if (chan_map[j] != -1) { + src = audio_stream_read_frag_s16(source, + in_frag + + chan_map[j]); + dest = audio_stream_write_frag_s16(sink, + out_frag); + *dest = *src; + } + out_frag++; + } + in_frag += audio_stream_get_channels(source); + } + return 0; +} + +static int smart_amp_process_s32(struct processing_module *mod, + struct input_stream_buffer *bsource, + struct output_stream_buffer *bsink, + uint32_t frames, int8_t *chan_map) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct audio_stream __sparse_cache *source = bsource->data; + struct audio_stream __sparse_cache *sink = bsink->data; + int32_t *src; + int32_t *dest; + uint32_t in_frag = 0; + uint32_t out_frag = 0; + int i; + int j; + + bsource->consumed += frames * source->channels * sizeof(int32_t); + for (i = 0; i < frames; i++) { + for (j = 0 ; j < sad->out_channels; j++) { + if (chan_map[j] != -1) { + src = audio_stream_read_frag_s32(source, + in_frag + + chan_map[j]); + dest = audio_stream_write_frag_s32(sink, + out_frag); + *dest = *src; + } + out_frag++; + } + in_frag += audio_stream_get_channels(source); + } + + return 0; +} + +static smart_amp_proc get_smart_amp_process(struct comp_dev *dev, + struct comp_buffer __sparse_cache *buf) +{ + switch (audio_stream_get_frm_fmt(&buf->stream)) { + case SOF_IPC_FRAME_S16_LE: + return smart_amp_process_s16; + case SOF_IPC_FRAME_S24_4LE: + case SOF_IPC_FRAME_S32_LE: + return smart_amp_process_s32; + default: + comp_err(dev, "smart_amp_process() error: not supported frame format"); + return NULL; + } +} + +static int smart_amp_process(struct processing_module *mod, + struct input_stream_buffer *input_buffers, int num_input_buffers, + struct output_stream_buffer *output_buffers, int num_output_buffers) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer __sparse_cache *fb_buf_c; + struct comp_buffer __sparse_cache *buf; + struct module_source_info __sparse_cache *mod_source_info; + struct input_stream_buffer *fb_input = NULL; + /* if there is only one input stream, it should be the source input */ + struct input_stream_buffer *src_input = &input_buffers[0]; + uint32_t avail_passthrough_frames; + uint32_t avail_frames = 0; + uint32_t sink_bytes; + uint32_t i; + + mod_source_info = module_source_info_acquire(mod->source_info); + + if (num_input_buffers == SMART_AMP_NUM_IN_PINS) + for (i = 0; i < num_input_buffers; i++) { + buf = attr_container_of(input_buffers[i].data, + struct comp_buffer __sparse_cache, + stream, __sparse_cache); + + if (IPC4_SINK_QUEUE_ID(buf->id) == SOF_SMART_AMP_FEEDBACK_QUEUE_ID) { + fb_input = &input_buffers[i]; + fb_buf_c = buf; + } else { + src_input = &input_buffers[i]; + } + } + + avail_passthrough_frames = src_input->size; + + if (fb_input) { + if (fb_buf_c->source && comp_get_state(dev, fb_buf_c->source) == dev->state) { + /* feedback */ + avail_frames = MIN(avail_passthrough_frames, + fb_input->size); + + sad->process(mod, fb_input, &output_buffers[0], + avail_frames, sad->config.feedback_ch_map); + } + } + + if (!avail_frames) + avail_frames = avail_passthrough_frames; + + /* bytes calculation */ + sink_bytes = avail_frames * + audio_stream_frame_bytes(output_buffers[0].data); + + /* process data */ + sad->process(mod, src_input, &output_buffers[0], + avail_frames, sad->config.source_ch_map); + + output_buffers[0].size = sink_bytes; + + module_source_info_release(mod_source_info); + return 0; +} + +static int smart_amp_reset(struct processing_module *mod) +{ + struct comp_dev *dev = mod->dev; + + comp_dbg(dev, "smart_amp_reset()"); + + return 0; +} + +static int smart_amp_prepare(struct processing_module *mod) +{ + struct smart_amp_data *sad = module_get_private_data(mod); + struct comp_dev *dev = mod->dev; + struct comp_buffer *source_buffer; + struct comp_buffer *sink_buffer; + struct comp_buffer __sparse_cache *buffer_c; + struct list_item *blist; + int ret; + + ret = smart_amp_params(mod); + if (ret < 0) + return ret; + + comp_dbg(dev, "smart_amp_prepare()"); + /* searching for stream and feedback source buffers */ + list_for_item(blist, &dev->bsource_list) { + source_buffer = container_of(blist, struct comp_buffer, + sink_list); + buffer_c = buffer_acquire(source_buffer); + audio_stream_init_alignment_constants(1, 1, &buffer_c->stream); + if (IPC4_SINK_QUEUE_ID(buffer_c->id) == SOF_SMART_AMP_FEEDBACK_QUEUE_ID) { + buffer_c->stream.channels = sad->config.feedback_channels; + buffer_c->stream.rate = mod->priv.cfg.base_cfg.audio_fmt.sampling_frequency; + } + buffer_release(buffer_c); + } + + sink_buffer = list_first_item(&dev->bsink_list, struct comp_buffer, source_list); + buffer_c = buffer_acquire(sink_buffer); + sad->out_channels = audio_stream_get_channels(&buffer_c->stream); + audio_stream_init_alignment_constants(1, 1, &buffer_c->stream); + sad->process = get_smart_amp_process(dev, buffer_c); + buffer_release(buffer_c); + + if (!sad->process) { + comp_err(dev, "smart_amp_prepare(): get_smart_amp_process failed"); + ret = -EINVAL; + } + return ret; +} + +static struct module_interface smart_amp_interface = { + .init = smart_amp_init, + .prepare = smart_amp_prepare, + .process = smart_amp_process, + .set_configuration = smart_amp_set_config, + .get_configuration = smart_amp_get_config, + .reset = smart_amp_reset, + .free = smart_amp_free +}; +DECLARE_MODULE_ADAPTER(smart_amp_interface, smart_amp_comp_uuid, smart_amp_comp_tr); +SOF_MODULE_INIT(smart_amp_test, sys_comp_module_smart_amp_interface_init); diff --git a/src/schedule/zephyr_dma_domain.c b/src/schedule/zephyr_dma_domain.c index eb0f57ba3467..41b01e3d6200 100644 --- a/src/schedule/zephyr_dma_domain.c +++ b/src/schedule/zephyr_dma_domain.c @@ -32,9 +32,17 @@ LOG_MODULE_DECLARE(ll_schedule, CONFIG_SOF_LOG_LEVEL); #define interrupt_disable mux_interrupt_disable #endif -#define SEM_LIMIT 1 +#ifdef CONFIG_ARM64 +#define interrupt_clear_mask(irq, bit) +#endif /* CONFIG_ARM64 */ + #define ZEPHYR_PDOMAIN_STACK_SIZE 8192 +/* sanity check - make sure CONFIG_DMA_DOMAIN_SEM_LIMIT is not some + * garbage value. + */ +BUILD_ASSERT(CONFIG_DMA_DOMAIN_SEM_LIMIT > 0, "Invalid DMA domain SEM_LIMIT"); + K_KERNEL_STACK_ARRAY_DEFINE(zephyr_dma_domain_stack, CONFIG_CORE_COUNT, ZEPHYR_PDOMAIN_STACK_SIZE); @@ -71,7 +79,7 @@ static int zephyr_dma_domain_unregister(struct ll_schedule_domain *domain, struct task *task, uint32_t num_tasks); static void zephyr_dma_domain_task_cancel(struct ll_schedule_domain *domain, - uint32_t num_tasks); + struct task *task); static const struct ll_schedule_domain_ops zephyr_dma_domain_ops = { .domain_register = zephyr_dma_domain_register, @@ -174,18 +182,6 @@ static int register_dma_irq(struct zephyr_dma_domain *domain, struct zephyr_dma_domain_data *crt_data; int i, j, irq, ret; - /* register the DMA IRQ only for PPL tasks marked as "registrable" - * - * this is done because, in case of mixer topologies there's - * multiple PPLs having the same scheduling component so there's - * no need to go through this function for all of those PPL - * tasks - only the PPL task containing the scheduling component - * will do the registering - * - */ - if (!pipe_task->registrable) - return 0; - /* iterate through all available channels in order to find a * suitable channel for which the DMA IRQs will be enabled. */ @@ -265,6 +261,16 @@ static int zephyr_dma_domain_register(struct ll_schedule_domain *domain, tr_info(&ll_tr, "zephyr_dma_domain_register()"); + /* don't even bother trying to register DMA IRQ for + * non-registrable tasks. + * + * this is needed because zephyr_dma_domain_register() will + * return -EINVAL for non-registrable tasks because of + * register_dma_irq() which is not right. + */ + if (!pipe_task->registrable) + return 0; + /* the DMA IRQ has to be registered before the Zephyr thread is * started. * @@ -293,11 +299,28 @@ static int zephyr_dma_domain_register(struct ll_schedule_domain *domain, dt->arg = arg; /* prepare work semaphore */ - k_sem_init(&dt->sem, 0, SEM_LIMIT); + k_sem_init(&dt->sem, 0, CONFIG_DMA_DOMAIN_SEM_LIMIT); thread_name[sizeof(thread_name) - 2] = '0' + core; /* create Zephyr thread */ + /* VERY IMPORTANT: DMA domain's priority needs to be + * in the cooperative range to avoid scenarios such + * as the following: + * + * 1) pipeline_copy() is in the middle of a pipeline + * graph traversal marking buffer->walking as true. + * 2) IPC TRIGGER STOP comes and since edf thread + * has a higher priority it will preempt the DMA domain + * thread. + * 3) When TRIGGER STOP handler does a pipeline graph + * traversal it will find some buffers with walking = true + * and not go through all the components in the pipeline. + * 4) TRIGGER RESET comes and the components are not + * stopped so the handler will try to stop them which + * results in DMA IRQs being stopped and the pipeline tasks + * being stuck in the scheduling queue. + */ thread = k_thread_create(&dt->ll_thread, zephyr_dma_domain_stack[core], ZEPHYR_PDOMAIN_STACK_SIZE, @@ -305,7 +328,7 @@ static int zephyr_dma_domain_register(struct ll_schedule_domain *domain, dt, NULL, NULL, - CONFIG_NUM_PREEMPT_PRIORITIES - 1, + -CONFIG_NUM_COOP_PRIORITIES, 0, K_FOREVER); @@ -365,17 +388,6 @@ static int unregister_dma_irq(struct zephyr_dma_domain *domain, struct zephyr_dma_domain_data *crt_data; struct dma *crt_dma; int i, j; - /* unregister the DMA IRQ only for PPL tasks marked as "registrable" - * - * this is done because, in case of mixer topologies there's - * multiple PPLs having the same scheduling component so there's - * no need to go through this function for all of those PPL - * tasks - only the PPL task containing the scheduling component - * will do the unregistering - * - */ - if (!pipe_task->registrable) - return 0; for (i = 0; i < domain->num_dma; i++) { crt_dma = domain->dma_array + i; @@ -426,6 +438,18 @@ static int zephyr_dma_domain_unregister(struct ll_schedule_domain *domain, tr_info(&ll_tr, "zephyr_dma_domain_unregister()"); + /* unregister the DMA IRQ only for PPL tasks marked as "registrable" + * + * this is done because, in case of mixer topologies there's + * multiple PPLs having the same scheduling component so there's + * no need to go through this function for all of those PPL + * tasks - only the PPL task containing the scheduling component + * will do the unregistering + * + */ + if (!pipe_task->registrable) + return 0; + ret = unregister_dma_irq(zephyr_dma_domain, pipe_task, core); if (ret < 0) { tr_err(&ll_tr, "failed to unregister DMA IRQ for pipe task %p on core %d", @@ -440,20 +464,29 @@ static int zephyr_dma_domain_unregister(struct ll_schedule_domain *domain, } static void zephyr_dma_domain_task_cancel(struct ll_schedule_domain *domain, - uint32_t num_tasks) + struct task *task) { struct zephyr_dma_domain *zephyr_dma_domain; struct zephyr_dma_domain_thread *dt; + struct pipeline_task *pipe_task; int core; zephyr_dma_domain = ll_sch_get_pdata(domain); core = cpu_get_id(); dt = zephyr_dma_domain->domain_thread + core; + pipe_task = pipeline_task_get(task); - if (!num_tasks) { - /* DMA IRQs got cut off, we need to let the Zephyr - * thread execute the handler one more time so as to be - * able to remove the task from the task queue + if (pipe_task->sched_comp->state != COMP_STATE_ACTIVE) { + /* If the state of the scheduling component + * corresponding to a pipeline task is != + * COMP_STATE_ACTIVE then that means the DMA IRQs are + * disabled. Because of this, when a task is cancelled + * we need to give resources to the semaphore to make + * sure that zephyr_ll_run() is still executed and the + * tasks can be safely cancelled. + * + * This works because the state of the scheduling + * component is updated before the trigger operation. */ k_sem_give(&dt->sem); } diff --git a/src/schedule/zephyr_ll.c b/src/schedule/zephyr_ll.c index a2e471063df4..7405dc0b22a9 100644 --- a/src/schedule/zephyr_ll.c +++ b/src/schedule/zephyr_ll.c @@ -439,7 +439,7 @@ static int zephyr_ll_task_cancel(void *data, struct task *task) if (task->state != SOF_TASK_STATE_FREE) { task->state = SOF_TASK_STATE_CANCEL; /* let domain know that a task has been cancelled */ - domain_task_cancel(sch->ll_domain, sch->n_tasks - 1); + domain_task_cancel(sch->ll_domain, task); } zephyr_ll_unlock(sch, &flags); diff --git a/test/cmocka/src/audio/buffer/CMakeLists.txt b/test/cmocka/src/audio/buffer/CMakeLists.txt index 403b5f7d8498..7f07e1abcb61 100644 --- a/test/cmocka/src/audio/buffer/CMakeLists.txt +++ b/test/cmocka/src/audio/buffer/CMakeLists.txt @@ -13,6 +13,7 @@ cmocka_test(buffer_copy ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) cmocka_test(buffer_new @@ -29,6 +30,7 @@ cmocka_test(buffer_new ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) cmocka_test(buffer_wrap @@ -45,6 +47,7 @@ cmocka_test(buffer_wrap ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) cmocka_test(buffer_write @@ -61,4 +64,5 @@ cmocka_test(buffer_write ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) diff --git a/test/cmocka/src/audio/component/CMakeLists.txt b/test/cmocka/src/audio/component/CMakeLists.txt index 115f14d236eb..a5868d259cf6 100644 --- a/test/cmocka/src/audio/component/CMakeLists.txt +++ b/test/cmocka/src/audio/component/CMakeLists.txt @@ -2,6 +2,7 @@ cmocka_test(comp_set_state comp_set_state.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ${PROJECT_SOURCE_DIR}/src/audio/component.c ${PROJECT_SOURCE_DIR}/src/audio/data_blob.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c diff --git a/test/cmocka/src/audio/pcm_converter/CMakeLists.txt b/test/cmocka/src/audio/pcm_converter/CMakeLists.txt index 85d4d1b04928..8d6f0779d294 100644 --- a/test/cmocka/src/audio/pcm_converter/CMakeLists.txt +++ b/test/cmocka/src/audio/pcm_converter/CMakeLists.txt @@ -3,6 +3,7 @@ if(CONFIG_FORMAT_FLOAT) cmocka_test(pcm_float_generic pcm_float.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ${PROJECT_SOURCE_DIR}/src/audio/pcm_converter/pcm_converter.c ${PROJECT_SOURCE_DIR}/src/audio/pcm_converter/pcm_converter_generic.c ${PROJECT_SOURCE_DIR}/src/audio/buffer.c diff --git a/test/cmocka/src/audio/pipeline/CMakeLists.txt b/test/cmocka/src/audio/pipeline/CMakeLists.txt index f1cff35f5ffa..88623ebe94d1 100644 --- a/test/cmocka/src/audio/pipeline/CMakeLists.txt +++ b/test/cmocka/src/audio/pipeline/CMakeLists.txt @@ -19,6 +19,7 @@ endif() cmocka_test(pipeline_new pipeline_new.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ${PROJECT_SOURCE_DIR}/src/audio/component.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c @@ -36,6 +37,7 @@ cmocka_test(pipeline_new cmocka_test(pipeline_connect_upstream pipeline_connect_upstream.c pipeline_connection_mocks.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ${PROJECT_SOURCE_DIR}/src/audio/component.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c @@ -53,6 +55,7 @@ cmocka_test(pipeline_connect_upstream cmocka_test(pipeline_free pipeline_free.c pipeline_connection_mocks.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ${PROJECT_SOURCE_DIR}/src/audio/component.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc3/helper.c ${PROJECT_SOURCE_DIR}/src/ipc/ipc-common.c diff --git a/test/cmocka/src/audio/selector/CMakeLists.txt b/test/cmocka/src/audio/selector/CMakeLists.txt index 301373c37689..41c7d68552e8 100644 --- a/test/cmocka/src/audio/selector/CMakeLists.txt +++ b/test/cmocka/src/audio/selector/CMakeLists.txt @@ -12,6 +12,7 @@ target_include_directories(selector_test PRIVATE ${PROJECT_SOURCE_DIR}/src/audio add_compile_options(-DUNIT_TEST) add_library(audio_for_selector STATIC + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ${PROJECT_SOURCE_DIR}/src/audio/selector/selector.c ${PROJECT_SOURCE_DIR}/src/audio/selector/selector_generic.c ${PROJECT_SOURCE_DIR}/src/audio/buffer.c diff --git a/test/cmocka/src/audio/volume/CMakeLists.txt b/test/cmocka/src/audio/volume/CMakeLists.txt index eab3729c7938..862dbe90c439 100644 --- a/test/cmocka/src/audio/volume/CMakeLists.txt +++ b/test/cmocka/src/audio/volume/CMakeLists.txt @@ -30,6 +30,7 @@ add_library(audio_for_volume STATIC ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-stream.c ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) sof_append_relative_path_definitions(audio_for_volume) diff --git a/test/cmocka/src/math/fft/CMakeLists.txt b/test/cmocka/src/math/fft/CMakeLists.txt index 1eba606b28eb..fba558ddf84e 100644 --- a/test/cmocka/src/math/fft/CMakeLists.txt +++ b/test/cmocka/src/math/fft/CMakeLists.txt @@ -19,4 +19,5 @@ cmocka_test(fft ${PROJECT_SOURCE_DIR}/src/audio/pipeline/pipeline-xrun.c ${PROJECT_SOURCE_DIR}/test/cmocka/src/common_mocks.c ${PROJECT_SOURCE_DIR}/src/audio/component.c + ${PROJECT_SOURCE_DIR}/src/math/numbers.c ) diff --git a/tools/test/audio/comp_run.sh b/tools/test/audio/comp_run.sh index 79db14410aaf..c7e8a24ee05e 100755 --- a/tools/test/audio/comp_run.sh +++ b/tools/test/audio/comp_run.sh @@ -27,7 +27,8 @@ FS_OUT=48000 FN_IN=input.raw FN_OUT=output.raw FN_TRACE:=trace.txt # This is default value if FN_TRACE is not set via -e option -VALGRIND=yes +VALGRIND=true +XTRUN= EOFHELP } @@ -42,67 +43,68 @@ parse_args () FS_IN=48000 FS_OUT= VALGRIND=true - DEBUG= + DEBUG=-q SOURCED_CONFIG=false FN_TRACE= EXTRA_OPTS= + XTRUN= while getopts ":he:t:" opt; do - case "${opt}" in - e) - FN_TRACE="${OPTARG}" - ;; - h) - usage - exit - ;; - t) - # shellcheck disable=SC1090 - source "${OPTARG}" - SOURCED_CONFIG=true - ;; - *) - usage - exit 1 - ;; - esac + case "${opt}" in + e) + FN_TRACE="${OPTARG}" + ;; + h) + usage + exit + ;; + t) + # shellcheck disable=SC1090 + source "${OPTARG}" + SOURCED_CONFIG=true + ;; + *) + usage + exit 1 + ;; + esac done shift $((OPTIND -1)) if ! "$SOURCED_CONFIG"; then - [ $# -eq 8 ] || { - usage "$0" - exit 1 - } - - COMP="$1" - DIRECTION="$2" - BITS_IN="$3" - BITS_OUT="$4" - FS_IN="$5" - FS_OUT="$6" - FN_IN="$7" - FN_OUT="$8" + [ $# -eq 8 ] || { + usage "$0" + exit 1 + } + + COMP="$1" + DIRECTION="$2" + BITS_IN="$3" + BITS_OUT="$4" + FS_IN="$5" + FS_OUT="$6" + FN_IN="$7" + FN_OUT="$8" fi if [[ -z $BITS_OUT ]]; then - BITS_OUT=$BITS_IN + BITS_OUT=$BITS_IN fi if [[ -z $FS_OUT ]]; then - FS_OUT=$FS_IN + FS_OUT=$FS_IN fi if [[ -z $CHANNELS_OUT ]]; then - CHANNELS_OUT=$CHANNELS_IN + CHANNELS_OUT=$CHANNELS_IN fi } delete_file_check () { if [ -f "$1" ]; then - rm -f "$1" + rm -f "$1" fi } @@ -111,28 +113,52 @@ run_testbench () delete_file_check "$FN_OUT" delete_file_check "$FN_TRACE" if [ -z "$FN_TRACE" ]; then - # shellcheck disable=SC2086 - $VALGRIND_CMD $CMD + # shellcheck disable=SC2086 + $VALGRIND_CMD $CMD else - # shellcheck disable=SC2086 - $VALGRIND_CMD $CMD 2> "$FN_TRACE" + # shellcheck disable=SC2086 + $VALGRIND_CMD $CMD 2> "$FN_TRACE" fi } parse_args "$@" -# Paths -HOST_ROOT=../../testbench/build_testbench -HOST_EXE=$HOST_ROOT/install/bin/testbench -HOST_LIB=$HOST_ROOT/sof_ep/install/lib -TPLG_LIB=$HOST_ROOT/sof_parser/install/lib +# Path to topologies TPLG_DIR=../../build_tools/test/topology +# Testbench path and executable +if [[ -z $XTRUN ]]; then + TESTBENCH=../../testbench/build_testbench/install/bin/testbench +else + BUILD_DIR=../../testbench/build_xt_testbench + TESTBENCH="$BUILD_DIR"/testbench + source "$BUILD_DIR"/xtrun_env.sh + XTRUN_CMD=$XTENSA_PATH/$XTRUN + if $VALGRIND; then + >&2 printf "WARNING: Ignoring VALGRIND with xt-run\n" + VALGRIND=false + fi +fi + +if $VALGRIND; then + VALGRIND_CMD="valgrind --leak-check=yes --error-exitcode=1" +else + VALGRIND_CMD= +fi + +HOST_EXE="$XTRUN_CMD $TESTBENCH" + # Use topology from component test topologies INFMT=s${BITS_IN}le OUTFMT=s${BITS_OUT}le TPLGFN=test-${DIRECTION}-ssp5-mclk-0-I2S-${COMP}-${INFMT}-${OUTFMT}-48k-24576k-codec.tplg TPLG=${TPLG_DIR}/${TPLGFN} +[ -f "$TPLG" ] || { + echo + echo "Error: topology $TPLG does not exist." + echo "Please run scripts/build-tools.sh -t" + exit 1 +} # If binary test vectors if [ "${FN_IN: -4}" == ".raw" ]; then @@ -146,17 +172,9 @@ OPTS="$DEBUG -r $FS_IN -R $FS_OUT -c $CHANNELS_IN -n $CHANNELS_OUT $BINFMT -t $T DATA="-i $FN_IN -o $FN_OUT" ARG="$OPTS $EXTRA_OPTS $DATA" CMD="$HOST_EXE $ARG" -if "$VALGRIND"; then - VALGRIND_CMD="valgrind --leak-check=yes --error-exitcode=1" -else - VALGRIND_CMD= -fi - -export LD_LIBRARY_PATH=$HOST_LIB:$TPLG_LIB # Run test bench echo "Command: $HOST_EXE" echo "Argument: $ARG" -echo "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" run_testbench diff --git a/tools/test/audio/process_test.m b/tools/test/audio/process_test.m index aaefe76a80a8..493abdb8ec92 100644 --- a/tools/test/audio/process_test.m +++ b/tools/test/audio/process_test.m @@ -1,12 +1,24 @@ % process_test - test objective audio quality parameters % -% process_test(comp, bits_in_list, bits_out_list, fs) +% process_test(comp, bits_in_list, bits_out_list, fs, fulltest, xtrun) +% +% Inputs +% comp - component to test +% bits_in_list - input word lengths +% bits_out_list - output workd lengths +% fs - sample rate +% fulltest - 0 perform only chirp test, 1 perform all +% xtrun - set to 'xt-run' or 'xt-run --turbo' to test with xt-testbench +% +% E.g. +% process_test('eq-iir', 32, 32, 48000, 0, 'xt-run --turbo'); +% process_test('eq-iir', 32, 32); % SPDX-License-Identifier: BSD-3-Clause % Copyright(c) 2017-2022 Intel Corporation. All rights reserved. % Author: Seppo Ingalsuo -function [n_fail, n_pass, n_na] = process_test(comp, bits_in_list, bits_out_list, fs, fulltest) +function [n_fail, n_pass, n_na] = process_test(comp, bits_in_list, bits_out_list, fs, fulltest, xtrun) %% Defaults for call parameters if nargin < 1 comp = 'EQIIR'; @@ -28,6 +40,10 @@ fulltest = 1; end + if nargin < 6 + xtrun = ''; + end + %% Paths t.blobpath = '../../topology/topology1/m4'; plots = 'plots'; @@ -44,6 +60,7 @@ t.bits_in = bits_in_list; % Input word length from func arguments t.bits_out = bits_out_list; % Output word length from func arguments t.full_test = fulltest; % 0 is quick check only, 1 is full test + t.xtrun = xtrun; %% Show graphics or not. With visible plot windows Octave may freeze if too % many windows are kept open. As workaround setting close windows to @@ -61,12 +78,14 @@ addpath('../../tune/eq'); mkdir_check(plots); mkdir_check(reports); - n_meas = 5; + n_meas = 6; n_bits_in = length(bits_in_list); n_bits_out = length(bits_out_list); r.bits_in_list = bits_in_list; r.bits_out_list = bits_out_list; r.g = NaN(n_bits_in, n_bits_out); + r.g_min = NaN(n_bits_in, n_bits_out); + r.g_max = NaN(n_bits_in, n_bits_out); r.dr = NaN(n_bits_in, n_bits_out); r.thdnf = NaN(n_bits_in, n_bits_out); r.pf = -ones(n_bits_in, n_bits_out, n_meas); @@ -89,11 +108,14 @@ [v(3), dr] = dr_test(t); [v(4), thdnf] = thdnf_test(t); v(5) = fr_test(t); + [v(6), g_min, g_max] = ldlg_test(t); % TODO: Collect results for all channels, now get worst-case r.g(a, b) = g(1); r.dr(a, b) = min(dr); r.thdnf(a, b) = max(thdnf); + r.g_min(a, b) = g_min; + r.g_max(a, b) = g_max; r.pf(a, b, :) = v; end @@ -126,10 +148,14 @@ fn = sprintf('%s/thdnf_%s_%d.txt', reports, t.comp, t.bits_in); print_val(t.comp, 'Worst-case THD+N vs. frequency', fn, bits_in_list, bits_out_list, r.thdnf, r.pf); + %% Print table with test summary: Level-dependent logarithmic gain + fn = sprintf('%s/ldlg_%s_%d.txt', reports, t.comp, t.bits_in); + print_val(t.comp, 'Level-dependent logarithmic gain min (dB)', fn, bits_in_list, bits_out_list, r.g_min, r.pf); + print_val(t.comp, 'Level-dependent logarithmic gain max (dB)', fn, bits_in_list, bits_out_list, r.g_max, r.pf); %% Print table with test summary: pass/fail fn = sprintf('%s/pf_%s_%d.txt', reports, t.comp, t.bits_in); - print_pf(t.comp', fn, bits_in_list, bits_out_list, r.pf, 'Fails chirp/gain/DR/THD+N/FR'); + print_pf(t.comp', fn, bits_in_list, bits_out_list, r.pf, 'Fails chirp/gain/DR/THD+N/FR/LDLG'); fprintf('\n'); fprintf('============================================================\n'); @@ -265,6 +291,29 @@ test_result_print(t, 'Frequency response', 'FR', test); end +%% Reference: AES17 8.1 Level-dependent logarithmic gain +function [fail, g_min, g_max] = ldlg_test(t) + test = test_defaults(t); + + % Create input file + test = ldlg_test_input(test); + + % Run test + test = test_run_process(test); + + % Measure + test = ldlg_test_measure(test); + test_result_print(t, 'Level-dependent gain', 'ldlg', test); + + % Get output parameters + fail = test.fail; + g_min = min(min(test.gain_db)); + g_max = max(max(test.gain_db)); + delete_check(t.files_delete, test.fn_in); + delete_check(t.files_delete, test.fn_out); +end + + %% ------------------------------------------------------------ %% Helper functions @@ -335,6 +384,7 @@ test.ch = t.ch; test.fs = t.fs; test.plot_visible = t.plot_visible; + test.xtrun = t.xtrun; % Misc test.quick = 0; diff --git a/tools/test/audio/std_utils/ldlg_test_input.m b/tools/test/audio/std_utils/ldlg_test_input.m new file mode 100644 index 000000000000..a5ae14329628 --- /dev/null +++ b/tools/test/audio/std_utils/ldlg_test_input.m @@ -0,0 +1,72 @@ +function test = ldlg_test_input(test) + +%% t = ldlg_test_input(t) +% +% Create tone data file for playback & record on real device or +% for algorithm simulation. +% +% Input parameters +% t.fs - sample rate +% t.bits_in - signal word length +% t.ch - mix test signal to channel ch +% t.nch - total number of channels in data +% +% Output parameters +% t.fn_in - created input file name +% t.fn_out - proposed output file name for captured output +% t.f - test signal frequency +% t.tl - tone length in seconds +% t.ts - tone start time +% t.tr - tone gain ramp length in seconds +% t.ti - ignore time from tone start and end, must be ti > tr +% t.a - tone amplitude (lin) +% t.a_db - tone amplitude (dB) +% t.mark_t - length of marker tone in seconds +% t.mark_a - amplitude max of marker tone (lin) +% t.mark_a_db - amplitude max of marker tone (dB) +% + +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2017 Intel Corporation. All rights reserved. +% Author: Seppo Ingalsuo + +%% Reference: AES17 8.1 Level-dependent logarithmic gain +% http://www.aes.org/publications/standards/ + +if nargin < 1 + fprintf('Warning, using default parameters!\n'); + test.fs = 48e3; test.bits=32; test.ch=1; test.nch=1; +end + +if test.ch == 0 + test.ch = 1+round(rand(1,1)*(test.nch-1)); % Test random channel 1..Nch +end + +for ch = test.ch + fprintf('Using parameters Fs=%.1f, bits_in=%d, ch=%d, Nch=%d\n', ... + test.fs/1e3, test.bits_in, ch, test.nch); +end + +id = floor(rand(1,1) * 1e6); +test.fn_in = sprintf('ldlg_test_in_%d.%s', id, test.fmt); +test.fn_out = sprintf('ldlg_test_out_%d.%s', id, test.fmt); +test.f = 997; + + +%% Tone sweep parameters +test.is = 30e-3; % Ignore signal from tone start +test.ie = 20e-3; % Ignore signal from tone end +test.tr = 10e-3; % Gain ramp time for tones +test.sm = 3; % Seek start marker from 3s from start +test.em = 3; % Seek end marker from 3s from end +test.mt = 0.3; % Error if marker positions delta is greater than 0.3s +test.tc = 25; % Min. 20 cycles of sine wave for a frequency +test.a_db = 0:-1:-60; % 0 to -60 dBFS +test.a = 10.^(test.a_db/20); +% 250ms seconds tone, this will be adjusted to be integer number of samples +test.tl = 250e-3; + +%% Mix the input file for test and write output +test = mix_sweep(test); + +end diff --git a/tools/test/audio/std_utils/ldlg_test_measure.m b/tools/test/audio/std_utils/ldlg_test_measure.m new file mode 100644 index 000000000000..957adc0a7e07 --- /dev/null +++ b/tools/test/audio/std_utils/ldlg_test_measure.m @@ -0,0 +1,80 @@ +function test = ldlg_test_measure(test) + +% SPDX-License-Identifier: BSD-3-Clause +% Copyright(c) 2017 Intel Corporation. All rights reserved. +% Author: Seppo Ingalsuo + +%% Reference: AES17 8.1 Level dependent logarithmic gain +% http://www.aes.org/publications/standards/ + +default_result = NaN * ones(test.na, length(test.ch)); +test.gain_db = default_result; + +%% Load output file +[x, nx] = load_test_output(test); + +if nx == 0 + test.fail = 1; + return +end + +%% 1/3 octave filter +fc = test.f; +bw = 1/3; +fmin = fc / sqrt(2^bw); +fmax = fmin * 2^bw; +wn = 2 * [fmin fmax] / test.fs; +[b, a] = butter(4, wn); +y0 = filter(b, a, x); + +%% Find sync +[d, nt, nt_use, nt_skip] = find_test_signal(x, test); +if isempty(d) + test.fail = 1; + return +end + +%% Measure gains for sweep +level_in = test.a_db(:); +for n=1:test.na + i1 = d + (n-1) * nt + nt_skip; + i2 = i1 + nt_use - 1; + level_out(n,:) = level_dbfs(y0(i1:i2,:)); +end + +test.gain_db = level_out - level_in + test.att_rec_db; +test.level_in_db = level_in; +test.level_out_db = level_out + test.att_rec_db; +test.fail = 0; + +test.fh(1) = figure('visible', test.plot_visible); +test.ph(1) = subplot(1, 1, 1); +if test.plot_channels_combine + plot(level_in, level_out); + hold on + p1 = min(level_in); + p2 = max(level_in); + plot([p1 p2], [p1 p2], 'k--'); + hold off + grid on + xlabel('Input level (dBFS)'); + ylabel('Output level (dBFS)'); + if test.nch == 2 + legend('ch1', 'ch2', 'Location', 'NorthWest'); + end +end + +test.fh(2) = figure('visible', test.plot_visible); +test.ph(2) = subplot(1, 1, 1); +if test.plot_channels_combine + plot(level_in, test.gain_db); + hold on + plot([p1 p2], [0 0], 'k--'); + hold off + grid on + xlabel('Input level (dBFS)'); + ylabel('Gain (dB)'); + if test.nch == 2 + legend('ch1', 'ch2'); + end +end diff --git a/tools/test/audio/test_utils/test_run.m b/tools/test/audio/test_utils/test_run.m index 85ac73586308..d4e78ce9127a 100644 --- a/tools/test/audio/test_utils/test_run.m +++ b/tools/test/audio/test_utils/test_run.m @@ -86,6 +86,12 @@ fprintf(fh, 'FN_TRACE=\"/dev/null"\n'); end +if isfield(test, 'xtrun') + fprintf(fh, 'XTRUN=\"%s\"\n', test.xtrun); +else + fprintf(fh, 'XTRUN=\n'); +end + % Override defaults in comp_run.sh fprintf(fh, 'VALGRIND=false\n'); fclose(fh); diff --git a/tools/testbench/common_test.c b/tools/testbench/common_test.c index 18606439faff..01a131773b37 100644 --- a/tools/testbench/common_test.c +++ b/tools/testbench/common_test.c @@ -29,6 +29,10 @@ #include "testbench/trace.h" #include +#if defined __XCC__ +#include +#endif + /* testbench helper functions for pipeline setup and trigger */ int tb_setup(struct sof *sof, struct testbench_prm *tp) @@ -46,13 +50,13 @@ int tb_setup(struct sof *sof, struct testbench_prm *tp) sys_comp_drc_init(); sys_comp_multiband_drc_init(); sys_comp_selector_init(); - sys_comp_src_init(); /* Module adapter components */ sys_comp_module_demux_interface_init(); sys_comp_module_eq_fir_interface_init(); sys_comp_module_eq_iir_interface_init(); sys_comp_module_mux_interface_init(); + sys_comp_module_src_interface_init(); sys_comp_module_tdfb_interface_init(); sys_comp_module_volume_interface_init(); @@ -281,3 +285,22 @@ void tb_enable_trace(bool enable) else debug_print("trace print disabled\n"); } + +void tb_gettime(struct timespec *td) +{ +#if !defined __XCC__ + clock_gettime(CLOCK_MONOTONIC, td); +#else + td->tv_nsec = 0; + td->tv_sec = 0; +#endif +} + +void tb_getcycles(uint64_t *cycles) +{ +#if defined __XCC__ + *cycles = XT_RSR_CCOUNT(); +#else + *cycles = 0; +#endif +} diff --git a/tools/testbench/file.c b/tools/testbench/file.c index 55adcbbcca60..062848e85ad1 100644 --- a/tools/testbench/file.c +++ b/tools/testbench/file.c @@ -617,6 +617,7 @@ static struct comp_dev *file_new(const struct comp_driver *drv, cd->fs.write_failed = false; cd->fs.n = 0; cd->fs.copy_count = 0; + cd->fs.cycles_count = 0; dev->state = COMP_STATE_READY; return dev; @@ -721,7 +722,7 @@ static int file_params(struct comp_dev *dev, samples = periods * dev->frames * stream->channels; switch (stream->frame_fmt) { case SOF_IPC_FRAME_S16_LE: - ret = buffer_set_size(buffer, samples * sizeof(int16_t)); + ret = buffer_set_size(buffer, samples * sizeof(int16_t), 0); if (ret < 0) { fprintf(stderr, "error: file buffer size set\n"); return ret; @@ -731,7 +732,7 @@ static int file_params(struct comp_dev *dev, cd->file_func = file_s16; break; case SOF_IPC_FRAME_S24_4LE: - ret = buffer_set_size(buffer, samples * sizeof(int32_t)); + ret = buffer_set_size(buffer, samples * sizeof(int32_t), 0); if (ret < 0) { fprintf(stderr, "error: file buffer size set\n"); return ret; @@ -741,7 +742,7 @@ static int file_params(struct comp_dev *dev, cd->file_func = file_s24; break; case SOF_IPC_FRAME_S32_LE: - ret = buffer_set_size(buffer, samples * sizeof(int32_t)); + ret = buffer_set_size(buffer, samples * sizeof(int32_t), 0); if (ret < 0) { fprintf(stderr, "error: file buffer size set\n"); return ret; @@ -803,11 +804,13 @@ static int file_copy(struct comp_dev *dev) struct comp_buffer *buffer; struct dai_data *dd = comp_get_drvdata(dev); struct file_comp_data *cd = comp_get_drvdata(dd->dai); + uint64_t cycles0, cycles1; int snk_frames; int src_frames; int bytes = cd->sample_container_bytes; int ret = 0; + tb_getcycles(&cycles0); switch (cd->fs.mode) { case FILE_READ: /* file component sink buffer */ @@ -859,6 +862,9 @@ static int file_copy(struct comp_dev *dev) cd->fs.reached_eof); schedule_task_cancel(dev->pipeline->pipe_task); } + + tb_getcycles(&cycles1); + cd->fs.cycles_count += cycles1 - cycles0; return ret; } diff --git a/tools/testbench/include/testbench/common_test.h b/tools/testbench/include/testbench/common_test.h index 588f95b52fc0..dd43c29ab0eb 100644 --- a/tools/testbench/include/testbench/common_test.h +++ b/tools/testbench/include/testbench/common_test.h @@ -36,6 +36,7 @@ struct tplg_context; * into per pipeline data and per topology data structures. */ struct testbench_prm { + long long total_cycles; char *tplg_file; /* topology file to use */ char *input_file[MAX_INPUT_FILE_NUM]; /* input file names */ char *output_file[MAX_OUTPUT_FILE_NUM]; /* output file names */ @@ -104,21 +105,8 @@ int tb_pipeline_reset(struct ipc *ipc, struct pipeline *p); void debug_print(char *message); -void sys_comp_asrc_init(void); -void sys_comp_crossover_init(void); -void sys_comp_dcblock_init(void); -void sys_comp_drc_init(void); -void sys_comp_eq_iir_init(void); -void sys_comp_mixer_init(void); -void sys_comp_multiband_drc_init(void); -void sys_comp_selector_init(void); -void sys_comp_src_init(void); - -void sys_comp_module_demux_interface_init(void); -void sys_comp_module_eq_fir_interface_init(void); -void sys_comp_module_eq_iir_interface_init(void); -void sys_comp_module_mux_interface_init(void); -void sys_comp_module_tdfb_interface_init(void); -void sys_comp_module_volume_interface_init(void); +void tb_gettime(struct timespec *td); + +void tb_getcycles(uint64_t *cycles); #endif diff --git a/tools/testbench/include/testbench/file.h b/tools/testbench/include/testbench/file.h index 14d5e80dfacc..d18f97972985 100644 --- a/tools/testbench/include/testbench/file.h +++ b/tools/testbench/include/testbench/file.h @@ -11,6 +11,8 @@ #ifndef _FILE_H #define _FILE_H +#include + /**< Convert with right shift a bytes count to samples count */ #define FILE_BYTES_TO_S16_SAMPLES(s) ((s) >> 1) #define FILE_BYTES_TO_S32_SAMPLES(s) ((s) >> 2) @@ -29,14 +31,15 @@ enum file_format { /* file component state */ struct file_state { - char *fn; + uint64_t cycles_count; FILE *rfh, *wfh; /* read/write file handle */ - bool reached_eof; - bool write_failed; + char *fn; + int copy_count; int n; enum file_mode mode; enum file_format f_format; - int copy_count; + bool reached_eof; + bool write_failed; }; /* file comp data */ diff --git a/tools/testbench/testbench.c b/tools/testbench/testbench.c index 8aa1446549ea..f4302765408f 100644 --- a/tools/testbench/testbench.c +++ b/tools/testbench/testbench.c @@ -254,7 +254,7 @@ static void test_pipeline_get_file_stats(int pipeline_id) time = cd->pipeline->pipe_task->start; if (fcd->fs.copy_count == 0) fcd->fs.copy_count = 1; - printf("file %s: id %d: type %d: samples %d copies %d total time %zu uS avg time %zu uS\n", + printf("file %s: id %d: type %d: samples %d copies %d total time %lu uS avg time %lu uS\n", fcd->fs.fn, cd->ipc_config.id, cd->drv->type, fcd->fs.n, fcd->fs.copy_count, time, time / fcd->fs.copy_count); break; @@ -356,7 +356,7 @@ static int parse_input_args(int argc, char **argv, struct testbench_prm *tp) default: fprintf(stderr, "unknown option %c\n", option); ret = -EINVAL; - __attribute__ ((fallthrough)); + /* fallthrough */ case 'h': print_usage(argv[0]); exit(EXIT_SUCCESS); @@ -487,10 +487,16 @@ static int test_pipeline_start(struct testbench_prm *tp) static bool test_pipeline_check_state(struct testbench_prm *tp, int state) { struct pipeline *p; + uint64_t cycles0, cycles1; int i; + tb_getcycles(&cycles0); + schedule_ll_run_tasks(); + tb_getcycles(&cycles1); + tp->total_cycles += cycles1 - cycles0; + /* Run pipeline until EOF from fileread */ for (i = 0; i < tp->pipeline_num; i++) { p = get_pipeline_by_id(tp->pipelines[i]); @@ -522,7 +528,7 @@ static int test_pipeline_load(struct testbench_prm *tp, struct tplg_context *ctx } static void test_pipeline_stats(struct testbench_prm *tp, - struct tplg_context *ctx, uint64_t delta) + struct tplg_context *ctx, long long delta_t) { int count = 1; struct ipc_comp_dev *icd; @@ -530,7 +536,9 @@ static void test_pipeline_stats(struct testbench_prm *tp, struct dai_data *dd; struct pipeline *p; struct file_comp_data *frcd, *fwcd; - int n_in, n_out; + long long file_cycles, pipeline_cycles; + float pipeline_mcps; + int n_in, n_out, frames_out; int i; /* Get pointer to filewrite */ @@ -566,6 +574,7 @@ static void test_pipeline_stats(struct testbench_prm *tp, n_in = frcd->fs.n; n_out = fwcd->fs.n; + file_cycles = frcd->fs.cycles_count + fwcd->fs.cycles_count; /* print test summary */ printf("==========================================================\n"); @@ -586,10 +595,25 @@ static void test_pipeline_stats(struct testbench_prm *tp, printf("Output[%d] written to file: \"%s\"\n", i, tp->output_file[i]); } + frames_out = n_out / tp->channels_out; printf("Input sample (frame) count: %d (%d)\n", n_in, n_in / tp->channels_in); - printf("Output sample (frame) count: %d (%d)\n", n_out, n_out / tp->channels_out); - printf("Total execution time: %zu us, %.2f x realtime\n\n", - delta, (double)((double)n_out / tp->channels_out / tp->fs_out) * 1000000 / delta); + printf("Output sample (frame) count: %d (%d)\n", n_out, frames_out); + if (tp->total_cycles) { + pipeline_cycles = tp->total_cycles - file_cycles; + pipeline_mcps = (float)pipeline_cycles * tp->fs_out / frames_out / 1e6; + printf("Total execution cycles: %lld\n", tp->total_cycles); + printf("File component cycles: %lld\n", file_cycles); + printf("Pipeline cycles: %lld\n", pipeline_cycles); + printf("Pipeline MCPS: %6.2f\n", pipeline_mcps); + if (!tp->quiet) + printf("Warning: Use -q to avoid printing to increase MCPS.\n"); + } + + if (delta_t) + printf("Total execution time: %lld us, %.2f x realtime\n", + delta_t, (float)frames_out / tp->fs_out * 1000000 / delta_t); + + printf("\n"); } /* @@ -602,10 +626,10 @@ static int pipline_test(struct testbench_prm *tp) struct tplg_context ctx; struct timespec ts; struct timespec td0, td1; + long long delta_t; int err; int nsleep_time; int nsleep_limit; - uint64_t delta; /* build, run and teardown pipelines */ while (dp_count < tp->dynamic_pipeline_iterations) { @@ -637,7 +661,8 @@ static int pipline_test(struct testbench_prm *tp) dp_count, err); break; } - clock_gettime(CLOCK_MONOTONIC, &td0); + + tb_gettime(&td0); /* sleep to let the pipeline work - we exit at timeout OR * if copy iterations OR max_samples is reached (whatever first) @@ -652,8 +677,12 @@ static int pipline_test(struct testbench_prm *tp) tp->pipeline_duration_ms; while (nsleep_time < nsleep_limit) { +#if defined __XCC__ + err = 0; +#else /* wait for next tick */ err = nanosleep(&ts, &ts); +#endif if (err == 0) { nsleep_time += tp->tick_period_us; /* sleep fully completed */ if (test_pipeline_check_state(tp, SOF_TASK_STATE_CANCEL)) { @@ -670,7 +699,8 @@ static int pipline_test(struct testbench_prm *tp) } } - clock_gettime(CLOCK_MONOTONIC, &td1); + tb_gettime(&td1); + err = test_pipeline_stop(tp); if (err < 0) { fprintf(stderr, "error: pipeline stop %d failed %d\n", @@ -678,9 +708,9 @@ static int pipline_test(struct testbench_prm *tp) break; } - delta = (td1.tv_sec - td0.tv_sec) * 1000000; - delta += (td1.tv_nsec - td0.tv_nsec) / 1000; - test_pipeline_stats(tp, &ctx, delta); + delta_t = (td1.tv_sec - td0.tv_sec) * 1000000; + delta_t += (td1.tv_nsec - td0.tv_nsec) / 1000; + test_pipeline_stats(tp, &ctx, delta_t); err = test_pipeline_reset(tp); if (err < 0) { @@ -705,6 +735,7 @@ int main(int argc, char **argv) /* initialize input and output sample rates, files, etc. */ debug = 0; + tp.total_cycles = 0; tp.fs_in = 0; tp.fs_out = 0; tp.bits_in = 0; diff --git a/tools/testbench/testbench_xcc_sections.txt b/tools/testbench/testbench_xcc_sections.txt new file mode 100644 index 000000000000..ab0d7668f8fd --- /dev/null +++ b/tools/testbench/testbench_xcc_sections.txt @@ -0,0 +1,18 @@ +# +# IRAM placement +# +# put: .iram0.text .literal +# put: .iram0.text .text + +#put: .iram0.text .static_uuids +#put: .iram0.text .trace_ctx +#put: .text .static_uuids +#put: .text .trace_ctx +put: .bss .static_uuids +put: .bss .trace_ctx + +# sections order + +# .text +# .static_uuids +# .trace_ctx diff --git a/tools/testbench/topology.c b/tools/testbench/topology.c index b47cbf873c6b..d943dc1a8793 100644 --- a/tools/testbench/topology.c +++ b/tools/testbench/topology.c @@ -7,7 +7,6 @@ /* Topology loader to set up components and pipeline */ -#include #include #include #include @@ -161,7 +160,7 @@ static int tb_register_pga(struct testbench_prm *tp, struct tplg_context *ctx) static int tb_register_pipeline(struct testbench_prm *tp, struct tplg_context *ctx) { struct sof *sof = ctx->sof; - struct sof_ipc_pipe_new pipeline = {0}; + struct sof_ipc_pipe_new pipeline = {{0}}; int ret; ret = tplg_new_pipeline(ctx, &pipeline, sizeof(pipeline), NULL); diff --git a/tools/topology/topology1/CMakeLists.txt b/tools/topology/topology1/CMakeLists.txt index 93389d3d505b..eb21aa2fe04c 100644 --- a/tools/topology/topology1/CMakeLists.txt +++ b/tools/topology/topology1/CMakeLists.txt @@ -51,6 +51,8 @@ set(TPLGS "sof-icl-rt711-rt1308-rt715-hdmi\;sof-adl-rt711-l0-rt1316-l13-rt714-l2\;-DPLATFORM=adl\;-DUAJ_LINK=0\;-DAMP_1_LINK=1\;-DAMP_2_LINK=3\;-DEXT_AMP_REF\;-DMIC_LINK=2" "sof-icl-rt711-rt1308-rt715-hdmi\;sof-adl-rt711-l2-rt1316-l01-rt714-l3\;-DPLATFORM=adl\;-DUAJ_LINK=2\;-DAMP_1_LINK=0\;-DAMP_2_LINK=1\;-DEXT_AMP_REF\;-DMIC_LINK=3" "sof-icl-rt711-rt1308-rt715-hdmi\;sof-adl-rt711-l2-rt1316-l01\;-DPLATFORM=adl\;-DUAJ_LINK=2\;-DAMP_1_LINK=0\;-DAMP_2_LINK=1\;-DEXT_AMP_REF\;-DNO_LOCAL_MIC" + "sof-icl-rt711-rt1308-rt715-hdmi\;sof-rpl-rt711-l2\;-DPLATFORM=rpl\;-DUAJ_LINK=2\;-DNOAMP\;-DNO_LOCAL_MIC" + "sof-icl-rt711-rt1308-rt715-hdmi\;sof-rpl-rt711-l0\;-DPLATFORM=rpl\;-DUAJ_LINK=0\;-DNOAMP\;-DNO_LOCAL_MIC" "sof-icl-rt711-rt1308-rt715-hdmi\;sof-rpl-rt711-l2-rt1316-l01-rt714-l3\;-DPLATFORM=rpl\;-DUAJ_LINK=2\;-DAMP_1_LINK=0\;-DAMP_2_LINK=1\;-DEXT_AMP_REF\;-DMIC_LINK=3" "sof-icl-rt711-rt1308-rt715-hdmi\;sof-rpl-rt711-l2-rt1316-l01\;-DPLATFORM=rpl\;-DUAJ_LINK=2\;-DAMP_1_LINK=0\;-DAMP_2_LINK=1\;-DEXT_AMP_REF\;-DNO_LOCAL_MIC" "sof-icl-rt711-rt1308-rt715-hdmi\;sof-rpl-rt711-l0-rt1318-l12-rt714-l3\;-DPLATFORM=rpl\;-DUAJ_LINK=0\;-DAMP_1_LINK=1\;-DAMP_2_LINK=2\;-DEXT_AMP_REF\;-DMIC_LINK=3" @@ -152,27 +154,33 @@ set(TPLGS "sof-imx8-wm8960-cs42888\;sof-imx8-wm8960-cs42888" "sof-imx8-cs42888\;sof-imx8-cs42888" "sof-imx8-nocodec-sai\;sof-imx8-nocodec-sai" - "sof-imx8-wm8960-mixer\;sof-imx8-wm8960-mixer" + "sof-imx8-wm8960-mixer\;sof-imx8-wm8960-mixer\;-DCODEC=wm8960\;-DRATE=48000\;-DSAI_INDEX=1" + "sof-imx8-wm8960-mixer\;sof-imx8-wm8962-mixer\;-DCODEC=wm8962\;-DRATE=48000\;-DSAI_INDEX=1" "sof-imx8-compr-wm8960-mixer\;sof-imx8-compr-wm8960-mixer" "sof-imx8-wm8960-kwd\;sof-imx8-wm8960-kwd" "sof-imx8-cs42888-mixer\;sof-imx8-cs42888-mixer" - "sof-imx8-wm8960\;sof-imx8-wm8960\;-DCODEC=wm8960\;-DPPROC=volume" - "sof-imx8-wm8960\;sof-imx8-wm8962\;-DCODEC=wm8962\;-DPPROC=volume" - "sof-imx8-wm8960\;sof-imx8-eq-iir-wm8960\;-DCODEC=wm8960\;-DPPROC=eq-iir-volume" - "sof-imx8-wm8960\;sof-imx8-eq-fir-wm8960\;-DCODEC=wm8960\;-DPPROC=eq-fir-volume" - "sof-imx8-wm8960\;sof-imx8-drc-wm8960\;-DCODEC=wm8960\;-DPPROC=drc" + "sof-imx8-wm8960\;sof-imx8-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=volume\;-DSAI_INDEX=1" + "sof-imx8-wm8960\;sof-imx8-wm8962\;-DCODEC=wm8962\;-DRATE=48000\;-DPPROC=volume\;-DSAI_INDEX=1" + "sof-imx8-wm8960\;sof-imx8-eq-iir-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=eq-iir-volume\;-DSAI_INDEX=1" + "sof-imx8-wm8960\;sof-imx8-eq-iir-wm8962\;-DCODEC=wm8962\;-DRATE=48000\;-DPPROC=eq-iir-volume\;-DSAI_INDEX=1" + "sof-imx8-wm8960\;sof-imx8-eq-fir-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=eq-fir-volume\;-DSAI_INDEX=1" + "sof-imx8-wm8960\;sof-imx8-eq-fir-wm8962\;-DCODEC=wm8962\;-DRATE=48000\;-DPPROC=eq-fir-volume\;-DSAI_INDEX=1" + "sof-imx8-wm8960\;sof-imx8-drc-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=drc\;-DSAI_INDEX=1" ## end i.MX8 (i.MX8QM and i.MX8QXP) topologies ## i.MX8MP topologies "sof-imx8mp-compr-wm8960-mixer\;sof-imx8mp-compr-wm8960-mixer" - "sof-imx8mp-wm8960-mixer\;sof-imx8mp-wm8960-mixer" + "sof-imx8-wm8960-mixer\;sof-imx8mp-wm8960-mixer\;-DCODEC=wm8960\;-DRATE=48000\;-DSAI_INDEX=3" + "sof-imx8-wm8960-mixer\;sof-imx8mp-wm8962-mixer\;-DCODEC=wm8962\;-DRATE=48000\;-DSAI_INDEX=3" "sof-imx8mp-wm8960-kwd\;sof-imx8mp-wm8960-kwd" - "sof-imx8mp-wm8960\;sof-imx8mp-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=volume" - "sof-imx8mp-wm8960\;sof-imx8mp-wm8904\;-DCODEC=wm8904\;-DRATE=44100\;-DPPROC=volume" - "sof-imx8mp-wm8960\;sof-imx8mp-wm8962\;-DCODEC=wm8962\;-DRATE=48000\;-DPPROC=volume" - "sof-imx8mp-wm8960\;sof-imx8mp-eq-iir-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=eq-iir-volume" - "sof-imx8mp-wm8960\;sof-imx8mp-eq-fir-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=eq-fir-volume" - "sof-imx8mp-wm8960\;sof-imx8mp-drc-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=drc" + "sof-imx8-wm8960\;sof-imx8mp-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=volume\;-DSAI_INDEX=3" + "sof-imx8-wm8960\;sof-imx8mp-wm8904\;-DCODEC=wm8904\;-DRATE=44100\;-DPPROC=volume\;-DSAI_INDEX=3" + "sof-imx8-wm8960\;sof-imx8mp-wm8962\;-DCODEC=wm8962\;-DRATE=48000\;-DPPROC=volume\;-DSAI_INDEX=3" + "sof-imx8-wm8960\;sof-imx8mp-eq-iir-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=eq-iir-volume\;-DSAI_INDEX=3" + "sof-imx8-wm8960\;sof-imx8mp-eq-iir-wm8962\;-DCODEC=wm8962\;-DRATE=48000\;-DPPROC=eq-iir-volume\;-DSAI_INDEX=3" + "sof-imx8-wm8960\;sof-imx8mp-eq-fir-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=eq-fir-volume\;-DSAI_INDEX=3" + "sof-imx8-wm8960\;sof-imx8mp-eq-fir-wm8962\;-DCODEC=wm8962\;-DRATE=48000\;-DPPROC=eq-fir-volume\;-DSAI_INDEX=3" + "sof-imx8-wm8960\;sof-imx8mp-drc-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=drc\;-DSAI_INDEX=3" ## end i.MX8MP topologies ## i.MX8ULP topologies @@ -182,6 +190,10 @@ set(TPLGS "sof-imx8ulp-9x9-btsco\;sof-imx8ulp-9x9-btsco-16k\;-DRATE=16000" ## end i.MX8ULP topologies + ## i.MX93 topologies + "sof-imx93-wm8962\;sof-imx93-wm8962\;-DPPROC=volume" + ## end i.MX93 topologies + "sof-mt8195-mt6359-rt1019-rt5682\;sof-mt8195-mt6359-rt1019-rt5682" "sof-mt8195-mt6359-rt1019-rt5682\;sof-mt8195-mt6359-rt1019-rt5682-dts\;-DDTS=`DTS'" "sof-mt8195-mt6359-rt1019-rt5682\;sof-mt8195-mt6359-max98390-rt5682" diff --git a/tools/topology/topology1/development/CMakeLists.txt b/tools/topology/topology1/development/CMakeLists.txt index 7ebe47da47a9..c95236706165 100644 --- a/tools/topology/topology1/development/CMakeLists.txt +++ b/tools/topology/topology1/development/CMakeLists.txt @@ -1,18 +1,28 @@ # SPDX-License-Identifier: BSD-3-Clause set(TPLGS - "sof-hda-asrc\;sof-hda-asrc-2ch\;-DCHANNELS=2" - "sof-tgl-nocodec-ci\;sof-tgl-nocodec-ci" - "sof-tgl-nocodec-ci\;sof-adl-nocodec-ci" - "sof-imx8mp-src-wm8960\;sof-imx8mp-src-wm8960" - "sof-imx8-src-wm8960\;sof-imx8-src-wm8960" + ## i.MX8 (i.MX8QM and i.MX8QXP) topologies + "sof-imx8-src-wm8960\;sof-imx8-src-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=src\;-DSAI_INDEX=1" + "sof-imx8-src-wm8960\;sof-imx8-src-wm8962\;-DCODEC=wm8962\;-DRATE=48000\;-DPPROC=src\;-DSAI_INDEX=1" "sof-imx8-src-cs42888\;sof-imx8-src-cs42888" - "sof-imx8-compr-wm8960\;sof-imx8-compr-wm8960" "sof-imx8-compr-pcm-wm8960\;sof-imx8-compr-pcm-wm8960" "sof-imx8-compr-pcm-cap-wm8960\;sof-imx8-compr-pcm-cap-wm8960" - "sof-imx8mp-compr-wm8960\;sof-imx8mp-compr-wm8960" + "sof-imx8-compr-wm8960\;sof-imx8-compr-wm8960\;-DCODEC=wm8960\;-DRATE=48000" + "sof-imx8-compr-wm8960\;sof-imx8-compr-wm8962\;-DCODEC=wm8962\;-DRATE=48000" + ## end i.MX8 (i.MX8QM and i.MX8QXP) topologies + + ## i.MX8MP topologies + "sof-imx8-src-wm8960\;sof-imx8mp-src-wm8960\;-DCODEC=wm8960\;-DRATE=48000\;-DPPROC=src\;-DSAI_INDEX=3" + "sof-imx8-src-wm8960\;sof-imx8mp-src-wm8962\;-DCODEC=wm8962\;-DRATE=48000\;-DPPROC=src\;-DSAI_INDEX=3" "sof-imx8mp-compr-pcm-wm8960\;sof-imx8mp-compr-pcm-wm8960" "sof-imx8mp-compr-pcm-cap-wm8960\;sof-imx8mp-compr-pcm-cap-wm8960" + "sof-imx8mp-compr-wm8960\;sof-imx8mp-compr-wm8960\;-DCODEC=wm8960\;-DRATE=48000" + "sof-imx8mp-compr-wm8960\;sof-imx8mp-compr-wm8962\;-DCODEC=wm8962\;-DRATE=48000" + ## end i.MX8MP topologies + + "sof-hda-asrc\;sof-hda-asrc-2ch\;-DCHANNELS=2" + "sof-tgl-nocodec-ci\;sof-tgl-nocodec-ci" + "sof-tgl-nocodec-ci\;sof-adl-nocodec-ci" "sof-hda-generic-kwd\;sof-hda-generic-2ch-kwd\;-DCHANNELS=2\;-DDYNAMIC=1" "sof-hda-generic-kwd\;sof-hda-generic-4ch-kwd\;-DCHANNELS=4\;-DDYNAMIC=1" ) diff --git a/tools/topology/topology1/development/sof-imx8-compr-pcm-cap-wm8960.m4 b/tools/topology/topology1/development/sof-imx8-compr-pcm-cap-wm8960.m4 index a302219bc992..436148af13d5 100644 --- a/tools/topology/topology1/development/sof-imx8-compr-pcm-cap-wm8960.m4 +++ b/tools/topology/topology1/development/sof-imx8-compr-pcm-cap-wm8960.m4 @@ -1,6 +1,7 @@ # # Topology with codec_adapter processing component for i.MX8QM/i.MX8QXP # +# This is just a passthrough for capture. # Include topology builder include(`utils.m4') @@ -26,7 +27,7 @@ include(`platform/imx/imx8.m4') # # Define the pipelines # -# PCM0 <---- volume <----- SAI3 (wm8960) +# PCM0 <---- Codec_Adapter <----- SAI1 (wm8960) # DECLARE_SOF_RT_UUID("passthrough_codec", passthrough_uuid, 0x376b5e44, 0x9c82, diff --git a/tools/topology/topology1/development/sof-imx8-compr-pcm-wm8960.m4 b/tools/topology/topology1/development/sof-imx8-compr-pcm-wm8960.m4 index eefc83250fc6..f20985a6bb47 100644 --- a/tools/topology/topology1/development/sof-imx8-compr-pcm-wm8960.m4 +++ b/tools/topology/topology1/development/sof-imx8-compr-pcm-wm8960.m4 @@ -1,6 +1,7 @@ # # Topology with codec_adapter processing component for i.MX8QM/i.MX8QXP # +# This is just a passthrough for playback. # Include topology builder include(`utils.m4') @@ -26,7 +27,7 @@ include(`platform/imx/imx8.m4') # # Define the pipelines # -# PCM0 ----> volume -----> SAI3 (wm8960) +# PCM0 ----> Codec_Adapter -----> SAI1 (wm8960) # DECLARE_SOF_RT_UUID("passthrough_codec", passthrough_uuid, 0x376b5e44, 0x9c82, diff --git a/tools/topology/topology1/development/sof-imx8-compr-wm8960.m4 b/tools/topology/topology1/development/sof-imx8-compr-wm8960.m4 index ebc1bcb22dc9..945b70f5d6dc 100644 --- a/tools/topology/topology1/development/sof-imx8-compr-wm8960.m4 +++ b/tools/topology/topology1/development/sof-imx8-compr-wm8960.m4 @@ -2,6 +2,7 @@ # Topology with codec_adapter processing component for i.MX8QM/i.MX8QXP # supporting following codecs: MP3, AAC. # +# This uses Cadence Codec libraries for playing MP3/AAC files. # Include topology builder include(`utils.m4') @@ -23,13 +24,13 @@ include(`platform/imx/imx8.m4') # Post process setup config - #codec Post Process setup config +#codec Post Process setup config # # Define the pipelines # -# PCM0 <----> volume <-----> SAI3 (wm8960) +# PCM0 ----> Codec_Adapter -----> SAI1 (`CODEC') # - +# CODEC: wm8960, wm8962 DECLARE_SOF_RT_UUID("Cadence Codec", cadence_codec_uuid, 0xd8218443, 0x5ff3, 0x4a4c, 0xb3, 0x88, 0x6c, 0xfe, 0x07, 0xb9, 0x56, 0xaa); @@ -64,12 +65,21 @@ dnl time_domain, sched_comp) PIPELINE_PCM_ADD(sof/pipe-codec-adapter-playback.m4, 1, 0, 2, s32le, 1000, 0, 0, - 48000, 48000, 48000) + `RATE', `RATE', `RATE') # # DAIs configuration # +# define STREAM_NAME, based on CODEC name +define(`STREAM_NAME', + `ifelse(CODEC, `wm8960', `wm8960-hifi', + CODEC, `wm8962', `wm8962', + `fatal_error(`Codec not supported.')')') + +# define DAI BE dai_link name +define(`DAI_BE_NAME', concat(`sai1-', STREAM_NAME)) + dnl DAI_ADD(pipeline, dnl pipe id, dai type, dai_index, dai_be, dnl buffer, periods, format, @@ -78,20 +88,29 @@ dnl period, priority, core, time_domain) # playback DAI is SAI3 using 2 periods # Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-playback.m4, - 1, SAI, 1, sai1-wm8960-hifi, + 1, SAI, 1, DAI_BE_NAME, PIPELINE_SOURCE_1, 2, s32le, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) # PCM Low Latency, id 0 -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) +dnl COMPR_PLAYBACK_ADD(name, pcm_id, playback) COMPR_PLAYBACK_ADD(Port0, 0, PIPELINE_PCM_1) dnl DAI_CONFIG(type, idx, link_id, name, sai_config) -DAI_CONFIG(SAI, 1, 0, sai1-wm8960-hifi, +DAI_CONFIG(SAI, 1, 0, DAI_BE_NAME, +ifelse( + CODEC, `wm8960', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_master), + SAI_CLOCK(fsync, `RATE', codec_master), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 1, 0)))', + CODEC, `wm8962', ` SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), SAI_CLOCK(bclk, 3072000, codec_master), - SAI_CLOCK(fsync, 48000, codec_master), + SAI_CLOCK(fsync, `RATE', codec_master), SAI_TDM(2, 32, 3, 3), - SAI_CONFIG_DATA(SAI, 1, 0))) + SAI_CONFIG_DATA(SAI, 1, 0)))', + ) diff --git a/tools/topology/topology1/development/sof-imx8-src-wm8960.m4 b/tools/topology/topology1/development/sof-imx8-src-wm8960.m4 index c2d578c3ff09..db7e86c1b5a7 100644 --- a/tools/topology/topology1/development/sof-imx8-src-wm8960.m4 +++ b/tools/topology/topology1/development/sof-imx8-src-wm8960.m4 @@ -1,5 +1,7 @@ # -# Topology for i.MX8QXP and i.MX8QM boards with wm8960 codec +# Topology for i.MX8QXP/i.MX8QM/i.MX8MP boards with `CODEC' codec +# +# CODEC: wm8960, wm8962 # # Include topology builder @@ -22,7 +24,7 @@ include(`platform/imx/imx8.m4') # # Define the pipelines # -# PCM0 <----> SRC <----> volume <-----> SAI1 (wm8960) +# PCM0 <----> SRC <----> volume <-----> `SAI_INDEX' (`CODEC') # dnl PIPELINE_PCM_ADD(pipeline, @@ -33,37 +35,46 @@ dnl time_domain, sched_comp) # Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. # Set 1000us deadline with priority 0 on core 0 -PIPELINE_PCM_ADD(sof/pipe-src-volume-playback.m4, +PIPELINE_PCM_ADD(sof/pipe-`PPROC'-volume-playback.m4, 1, 0, 2, s32le, 1000, 0, 0, - 8000, 96000, 48000) + 8000, 96000, `RATE') # Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. # Set 1000us deadline with priority 0 on core 0 -PIPELINE_PCM_ADD(sof/pipe-src-volume-capture.m4, +PIPELINE_PCM_ADD(sof/pipe-`PPROC'-volume-capture.m4, 2, 0, 2, s32le, 1000, 0, 0, - 8000, 96000, 48000) + 8000, 96000, `RATE') # # DAIs configuration # +# define STREAM_NAME, based on CODEC name +define(`STREAM_NAME', + `ifelse(CODEC, `wm8960', `-wm8960-hifi', + CODEC, `wm8962', `-wm8962', + `fatal_error(`Codec not supported.')')') + +# define DAI BE dai_link name +define(`DAI_BE_NAME', concat(concat(`sai', SAI_INDEX), STREAM_NAME)) + dnl DAI_ADD(pipeline, dnl pipe id, dai type, dai_index, dai_be, dnl buffer, periods, format, dnl period, priority, core, time_domain) -# playback DAI is SAI1 using 2 periods +# playback DAI is SAI_SAI_INDEX using 2 periods # Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-playback.m4, - 1, SAI, 1, sai1-wm8960-hifi, + 1, SAI, SAI_INDEX, DAI_BE_NAME, PIPELINE_SOURCE_1, 2, s32le, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) -# capture DAI is SAI1 using 2 periods +# capture DAI is SAI_SAI_INDEX using 2 periods # Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-capture.m4, - 2, SAI, 1, sai1-wm8960-hifi, + 2, SAI, SAI_INDEX, DAI_BE_NAME, PIPELINE_SINK_2, 2, s32le, 1000, 0, 0) @@ -74,9 +85,18 @@ dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) PCM_DUPLEX_ADD(Port0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) dnl DAI_CONFIG(type, idx, link_id, name, sai_config) -DAI_CONFIG(SAI, 1, 0, sai1-wm8960-hifi, +DAI_CONFIG(SAI, SAI_INDEX, 0, DAI_BE_NAME, +ifelse( + CODEC, `wm8960', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_master), + SAI_CLOCK(fsync, RATE, codec_master), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, SAI_INDEX, 0)))', + CODEC, `wm8962', ` SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), SAI_CLOCK(bclk, 3072000, codec_master), - SAI_CLOCK(fsync, 48000, codec_master), + SAI_CLOCK(fsync, `RATE', codec_master), SAI_TDM(2, 32, 3, 3), - SAI_CONFIG_DATA(SAI, 1, 0))) + SAI_CONFIG_DATA(SAI, SAI_INDEX, 0)))', + ) diff --git a/tools/topology/topology1/development/sof-imx8mp-compr-pcm-cap-wm8960.m4 b/tools/topology/topology1/development/sof-imx8mp-compr-pcm-cap-wm8960.m4 index 23e503657992..e2cf0a2f22d6 100644 --- a/tools/topology/topology1/development/sof-imx8mp-compr-pcm-cap-wm8960.m4 +++ b/tools/topology/topology1/development/sof-imx8mp-compr-pcm-cap-wm8960.m4 @@ -1,6 +1,7 @@ # # Topology with codec_adapter processing component for i.MX8MP # +# This is just a passthrough for capture. # Include topology builder include(`utils.m4') @@ -26,7 +27,7 @@ include(`platform/imx/imx8.m4') # # Define the pipelines # -# PCM0 <---- volume <----- SAI3 (wm8960) +# PCM0 <---- Codec_Adapter <----- SAI3 (wm8960) # DECLARE_SOF_RT_UUID("passthrough_codec", passthrough_uuid, 0x376b5e44, 0x9c82, 0x4ec2, diff --git a/tools/topology/topology1/development/sof-imx8mp-compr-pcm-wm8960.m4 b/tools/topology/topology1/development/sof-imx8mp-compr-pcm-wm8960.m4 index 625b29bec90f..d72e2ce6540d 100644 --- a/tools/topology/topology1/development/sof-imx8mp-compr-pcm-wm8960.m4 +++ b/tools/topology/topology1/development/sof-imx8mp-compr-pcm-wm8960.m4 @@ -1,6 +1,7 @@ # # Topology with codec_adapter processing component for i.MX8MP # +# This is just a passthrough for playback. # Include topology builder include(`utils.m4') @@ -26,7 +27,7 @@ include(`platform/imx/imx8.m4') # # Define the pipelines # -# PCM0 ----> volume -----> SAI3 (wm8960) +# PCM0 ----> Codec_Adapter -----> SAI3 (wm8960) # DECLARE_SOF_RT_UUID("passthrough_codec", passthrough_uuid, 0x376b5e44, 0x9c82, 0x4ec2, diff --git a/tools/topology/topology1/development/sof-imx8mp-compr-wm8960.m4 b/tools/topology/topology1/development/sof-imx8mp-compr-wm8960.m4 index 0f9850966f49..72a7b62ac7cc 100644 --- a/tools/topology/topology1/development/sof-imx8mp-compr-wm8960.m4 +++ b/tools/topology/topology1/development/sof-imx8mp-compr-wm8960.m4 @@ -1,6 +1,8 @@ # # Topology with codec_adapter processing component for i.MX8MP # supporting following codecs: MP3, AAC. +# +# This uses Cadence Codec libraries for playing MP3/AAC files. # Include topology builder include(`utils.m4') @@ -22,13 +24,13 @@ include(`platform/imx/imx8.m4') # Post process setup config - #codec Post Process setup config +# codec Post Process setup config # # Define the pipelines # -# PCM0 <----> volume <-----> SAI3 (wm8960) +# PCM0 ----> Codec_Adapter -----> SAI3 (`CODEC') # - +# CODEC: wm8960, wm8962 DECLARE_SOF_RT_UUID("Cadence Codec", cadence_codec_uuid, 0xd8218443, 0x5ff3, 0x4a4c, 0xb3, 0x88, 0x6c, 0xfe, 0x07, 0xb9, 0x56, 0xaa); @@ -64,12 +66,21 @@ dnl time_domain, sched_comp) PIPELINE_PCM_ADD(sof/pipe-codec-adapter-playback.m4, 1, 0, 2, s32le, 1000, 0, 0, - 48000, 48000, 48000) + `RATE', `RATE', `RATE') # # DAIs configuration # +# define STREAM_NAME, based on CODEC name +define(`STREAM_NAME', + `ifelse(CODEC, `wm8960', `wm8960-hifi', + CODEC, `wm8962', `wm8962', + `fatal_error(`Codec not supported.')')') + +# define DAI BE dai_link name +define(`DAI_BE_NAME', concat(`sai3-', STREAM_NAME)) + dnl DAI_ADD(pipeline, dnl pipe id, dai type, dai_index, dai_be, dnl buffer, periods, format, @@ -78,20 +89,29 @@ dnl period, priority, core, time_domain) # playback DAI is SAI3 using 2 periods # Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-playback.m4, - 1, SAI, 3, sai3-wm8960-hifi, + 1, SAI, 3, DAI_BE_NAME, PIPELINE_SOURCE_1, 2, s32le, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) # PCM Low Latency, id 0 -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) +dnl COMPR_PLAYBACK_ADD(name, pcm_id, playback) COMPR_PLAYBACK_ADD(Port0, 0, PIPELINE_PCM_1) dnl DAI_CONFIG(type, idx, link_id, name, sai_config) -DAI_CONFIG(SAI, 3, 0, sai3-wm8960-hifi, +DAI_CONFIG(SAI, 3, 0, DAI_BE_NAME, +ifelse( + CODEC, `wm8960', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_master), + SAI_CLOCK(fsync, `RATE', codec_master), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, 3, 0)))', + CODEC, `wm8962', ` SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), SAI_CLOCK(bclk, 3072000, codec_master), - SAI_CLOCK(fsync, 48000, codec_master), + SAI_CLOCK(fsync, `RATE', codec_master), SAI_TDM(2, 32, 3, 3), - SAI_CONFIG_DATA(SAI, 3, 0))) + SAI_CONFIG_DATA(SAI, 3, 0)))', + ) diff --git a/tools/topology/topology1/m4/buffer.m4 b/tools/topology/topology1/m4/buffer.m4 index 9a8f5b73f8f4..376e206c6c09 100644 --- a/tools/topology/topology1/m4/buffer.m4 +++ b/tools/topology/topology1/m4/buffer.m4 @@ -44,6 +44,8 @@ dnl COMP_BUFFER_SIZE( num_periods, sample_size, channels, fmames) define(`COMP_BUFFER_SIZE', `eval(`$1 * $2 * $3 * $4')') dnl COMP_PERIOD_FRAMES( sample_rate, period_us) -define(`COMP_PERIOD_FRAMES', `eval(`($1 * $2) / 1000000')') +dnl note: m4 eval arithmetic is 32bit signed, so split the 10^6 +dnl division to avoid overflow. +define(`COMP_PERIOD_FRAMES', `eval(`$1 / 100 * $2 / 10000')') divert(0)dnl diff --git a/tools/topology/topology1/sof-imx8-wm8960-mixer.m4 b/tools/topology/topology1/sof-imx8-wm8960-mixer.m4 index 8e5e52a30f78..ed2c63ea13ce 100644 --- a/tools/topology/topology1/sof-imx8-wm8960-mixer.m4 +++ b/tools/topology/topology1/sof-imx8-wm8960-mixer.m4 @@ -1,5 +1,7 @@ # -# Topology for i.MX8QM / i.MX8QXP boards with wm8960 codec demonstrating mixer component +# Topology for i.MX8QM/i.MX8QXP/i.MX8MP boards with `CODEC' codec demonstrating mixer component +# +# CODEC: wm8960, wm8962 # # Include topology builder @@ -21,9 +23,9 @@ include(`platform/imx/imx8.m4') # Define the pipelines # # PCM0 -----> volume -------v -# low latency mixer ----> volume ----> SAI1 +# low latency mixer ----> volume ----> `SAI_INDEX' (`CODEC') # PCM1 -----> volume -------^ -# PCM0 <---- Volume <---- SAI1 +# PCM0 <---- Volume <---- `SAI_INDEX' # # Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. @@ -31,23 +33,32 @@ include(`platform/imx/imx8.m4') PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4, 2, 0, 2, s32le, 1000, 0, 0, - 48000, 48000, 48000) + `RATE', `RATE', `RATE') # # DAI configuration # -# SAI port 1 is our only pipeline DAI +# SAI port SAI_INDEX is our only pipeline DAI # -# playback DAI is SAI1 using 2 periods +# define STREAM_NAME, based on CODEC name +define(`STREAM_NAME', + `ifelse(CODEC, `wm8960', `-wm8960-hifi', + CODEC, `wm8962', `-wm8962', + `fatal_error(`Codec not supported.')')') + +# define DAI BE dai_link name +define(`DAI_BE_NAME', concat(concat(`sai', SAI_INDEX), STREAM_NAME)) + +# playback DAI is SAI_SAI_INDEX using 2 periods # Buffers use s32le format, 1000us deadline on core 0 with priority 1 # this defines pipeline 1. The 'NOT_USED_IGNORED' is due to dependencies # and is adjusted later with an explicit dapm line. DAI_ADD(sof/pipe-mixer-volume-dai-playback.m4, - 1, SAI, 1, sai1-wm8960-hifi, + 1, SAI, SAI_INDEX, DAI_BE_NAME, NOT_USED_IGNORED, 2, s32le, 1000, 1, 0, SCHEDULE_TIME_DOMAIN_DMA, - 2, 48000) + 2, `RATE') # PCM Playback pipeline 3 on PCM 0 using max 2 channels of s32le. # 1000us deadline with priority 0 on core 0 @@ -55,7 +66,7 @@ DAI_ADD(sof/pipe-mixer-volume-dai-playback.m4, PIPELINE_PCM_ADD(sof/pipe-host-volume-playback.m4, 3, 0, 2, s32le, 1000, 0, 0, - 48000, 48000, 48000, + `RATE', `RATE', `RATE', SCHEDULE_TIME_DOMAIN_DMA, PIPELINE_PLAYBACK_SCHED_COMP_1) @@ -65,7 +76,7 @@ PIPELINE_PCM_ADD(sof/pipe-host-volume-playback.m4, PIPELINE_PCM_ADD(sof/pipe-host-volume-playback.m4, 4, 1, 2, s32le, 5000, 0, 0, - 48000, 48000, 48000, + `RATE', `RATE', `RATE', SCHEDULE_TIME_DOMAIN_DMA, PIPELINE_PLAYBACK_SCHED_COMP_1) @@ -82,11 +93,11 @@ SectionGraph."PIPE_NAME" { ] } -# capture DAI is SAI1 using 2 periods +# capture DAI is SAI_SAI_INDEX using 2 periods # Buffers use s32le format, 1000us deadline with priority 0 on core 0 # this is part of pipeline 2 DAI_ADD(sof/pipe-dai-capture.m4, - 2, SAI, 1, sai1-wm8960-hifi, + 2, SAI, SAI_INDEX, DAI_BE_NAME, PIPELINE_SINK_2, 2, s32le, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) @@ -98,9 +109,18 @@ PCM_PLAYBACK_ADD(PCM Deep Buffer, 1, PIPELINE_PCM_4) # # BE configurations # -DAI_CONFIG(SAI, 1, 0, sai1-wm8960-hifi, - SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), - SAI_CLOCK(bclk, 3072000, codec_master), - SAI_CLOCK(fsync, 48000, codec_master), - SAI_TDM(2, 16, 3, 3), - SAI_CONFIG_DATA(SAI, 1, 0))) +DAI_CONFIG(SAI, SAI_INDEX, 0, DAI_BE_NAME, +ifelse( + CODEC, `wm8960', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_master), + SAI_CLOCK(fsync, RATE, codec_master), + SAI_TDM(2, 16, 3, 3), + SAI_CONFIG_DATA(SAI, SAI_INDEX, 0)))', + CODEC, `wm8962', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_master), + SAI_CLOCK(fsync, RATE, codec_master), + SAI_TDM(2, 16, 3, 3), + SAI_CONFIG_DATA(SAI, SAI_INDEX, 0)))', + ) diff --git a/tools/topology/topology1/sof-imx8-wm8960.m4 b/tools/topology/topology1/sof-imx8-wm8960.m4 index 15b1d95b543b..e7339ae60bf2 100644 --- a/tools/topology/topology1/sof-imx8-wm8960.m4 +++ b/tools/topology/topology1/sof-imx8-wm8960.m4 @@ -1,5 +1,5 @@ # -# Topology for i.MX8QM/i.MX8QXP board with 'CODEC' codec +# Topology for i.MX8QM/i.MX8QXP/i.MX8MP board with 'CODEC' codec # # CODEC: wm8960, wm8962 # @@ -24,7 +24,7 @@ include(`platform/imx/imx8.m4') # # Define the pipelines # -# PCM0 <----> volume <-----> SAI1 (CODEC) +# PCM0 <----> `PPROC' <-----> `SAI_INDEX' (`CODEC') # dnl PIPELINE_PCM_ADD(pipeline, @@ -38,43 +38,44 @@ dnl time_domain, sched_comp) PIPELINE_PCM_ADD(sof/pipe-`PPROC'-playback.m4, 1, 0, 2, s32le, 1000, 0, 0, - 48000, 48000, 48000) + `RATE', `RATE', `RATE') # Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. # Set 1000us deadline with priority 0 on core 0 PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, 2, 0, 2, s32le, 1000, 0, 0, - 48000, 48000, 48000) + `RATE', `RATE', `RATE') # # DAIs configuration # # define STREAM_NAME, based on CODEC name define(`STREAM_NAME', - `ifelse(CODEC, `wm8960', `wm8960-hifi', - CODEC, `wm8962', `wm8962', - `fatal_error(`Codec not supported.')')') + `ifelse(CODEC, `wm8960', `-wm8960-hifi', + CODEC, `wm8904', `-wm8904-hifi', + CODEC, `wm8962', `-wm8962', + `fatal_error(`Codec not supported.')')') # define DAI BE dai_link name -define(`DAI_BE_NAME', concat(`sai1-', STREAM_NAME)) +define(`DAI_BE_NAME', concat(concat(`sai', SAI_INDEX), STREAM_NAME)) dnl DAI_ADD(pipeline, dnl pipe id, dai type, dai_index, dai_be, dnl buffer, periods, format, dnl period, priority, core, time_domain) -# playback DAI is SAI1 using 2 periods +# playback DAI is SAI_SAI_INDEX using 2 periods # Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-playback.m4, - 1, SAI, 1, DAI_BE_NAME, + 1, SAI, SAI_INDEX, DAI_BE_NAME, PIPELINE_SOURCE_1, 2, s32le, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) -# capture DAI is SAI1 using 2 periods +# capture DAI is SAI_SAI_INDEX using 2 periods # Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-capture.m4, - 2, SAI, 1, DAI_BE_NAME, + 2, SAI, SAI_INDEX, DAI_BE_NAME, PIPELINE_SINK_2, 2, s32le, 1000, 0, 0) @@ -85,9 +86,24 @@ dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) PCM_DUPLEX_ADD(Port0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) dnl DAI_CONFIG(type, idx, link_id, name, sai_config) -DAI_CONFIG(SAI, 1, 0, DAI_BE_NAME, +DAI_CONFIG(SAI, SAI_INDEX, 0, DAI_BE_NAME, +ifelse( + CODEC, `wm8960', ` SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), SAI_CLOCK(bclk, 3072000, codec_master), - SAI_CLOCK(fsync, 48000, codec_master), + SAI_CLOCK(fsync, RATE, codec_master), SAI_TDM(2, 32, 3, 3), - SAI_CONFIG_DATA(SAI, 1, 0))) + SAI_CONFIG_DATA(SAI, SAI_INDEX, 0)))', + CODEC, `wm8904', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 11565177, codec_mclk_in), + SAI_CLOCK(bclk, 1411200, codec_provider), + SAI_CLOCK(fsync, RATE, codec_provider), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, SAI_INDEX, 0)))', + CODEC, `wm8962', ` + SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), + SAI_CLOCK(bclk, 3072000, codec_master), + SAI_CLOCK(fsync, RATE, codec_master), + SAI_TDM(2, 32, 3, 3), + SAI_CONFIG_DATA(SAI, SAI_INDEX, 0)))', + ) diff --git a/tools/topology/topology1/sof-imx8mp-wm8960-mixer.m4 b/tools/topology/topology1/sof-imx8mp-wm8960-mixer.m4 deleted file mode 100644 index 6aa2a44ef579..000000000000 --- a/tools/topology/topology1/sof-imx8mp-wm8960-mixer.m4 +++ /dev/null @@ -1,106 +0,0 @@ -# -# Topology for i.MX8MP board with wm8960 codec demonstrating mixer component -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`sai.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include DSP configuration -include(`platform/imx/imx8.m4') - -# -# Define the pipelines -# -# PCM0 -----> volume -------v -# low latency mixer ----> volume ----> SAI3 -# PCM1 -----> volume -------^ -# PCM0 <---- Volume <---- SAI3 -# - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. -# 1000us deadline with priority 0 on core 0 -PIPELINE_PCM_ADD(sof/pipe-low-latency-capture.m4, - 2, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000) - -# -# DAI configuration -# -# SAI port 3 is our only pipeline DAI -# - -# playback DAI is SAI3 using 2 periods -# Buffers use s32le format, 1000us deadline on core 0 with priority 1 -# this defines pipeline 1. The 'NOT_USED_IGNORED' is due to dependencies -# and is adjusted later with an explicit dapm line. -DAI_ADD(sof/pipe-mixer-volume-dai-playback.m4, - 1, SAI, 3, sai3-wm8960-hifi, - NOT_USED_IGNORED, 2, s32le, - 1000, 1, 0, SCHEDULE_TIME_DOMAIN_DMA, - 2, 48000) - -# PCM Playback pipeline 3 on PCM 0 using max 2 channels of s32le. -# 1000us deadline with priority 0 on core 0 -# this is connected to pipeline DAI 1 -PIPELINE_PCM_ADD(sof/pipe-host-volume-playback.m4, - 3, 0, 2, s32le, - 1000, 0, 0, - 48000, 48000, 48000, - SCHEDULE_TIME_DOMAIN_DMA, - PIPELINE_PLAYBACK_SCHED_COMP_1) - -# PCM Playback pipeline 4 on PCM 1 using max 2 channels of s32le. -# 5ms deadline with priority 0 on core 0 -# this is connected to pipeline DAI 1 -PIPELINE_PCM_ADD(sof/pipe-host-volume-playback.m4, - 4, 1, 2, s32le, - 5000, 0, 0, - 48000, 48000, 48000, - SCHEDULE_TIME_DOMAIN_DMA, - PIPELINE_PLAYBACK_SCHED_COMP_1) - -# Connect pipelines together -SectionGraph."PIPE_NAME" { - index "0" - - lines [ - # PCM pipeline 3 to DAI pipeline 1 - dapm(PIPELINE_MIXER_1, PIPELINE_SOURCE_3) - # PCM pipeline 4 to DAI pipeline 1 - dapm(PIPELINE_MIXER_1, PIPELINE_SOURCE_4) - - ] -} - -# capture DAI is SAI3 using 2 periods -# Buffers use s32le format, 1000us deadline with priority 0 on core 0 -# this is part of pipeline 2 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SAI, 3, sai3-wm8960-hifi, - PIPELINE_SINK_2, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - - -# PCM definitions -PCM_DUPLEX_ADD(PCM, 0, PIPELINE_PCM_3, PIPELINE_PCM_2) -PCM_PLAYBACK_ADD(PCM Deep Buffer, 1, PIPELINE_PCM_4) - -# -# BE configurations -# -DAI_CONFIG(SAI, 3, 0, sai3-wm8960-hifi, - SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), - SAI_CLOCK(bclk, 3072000, codec_master), - SAI_CLOCK(fsync, 48000, codec_master), - SAI_TDM(2, 16, 3, 3), - SAI_CONFIG_DATA(SAI, 3, 0))) diff --git a/tools/topology/topology1/sof-imx8mp-wm8960.m4 b/tools/topology/topology1/sof-imx8mp-wm8960.m4 deleted file mode 100644 index 0dd4bb85c7af..000000000000 --- a/tools/topology/topology1/sof-imx8mp-wm8960.m4 +++ /dev/null @@ -1,108 +0,0 @@ -# -# Topology for i.MX8MP board with `CODEC' codec -# -# CODEC: wm8960, wm8904, wm8962 -# - -# Include topology builder -include(`utils.m4') -include(`dai.m4') -include(`pipeline.m4') -include(`sai.m4') -include(`pcm.m4') -include(`buffer.m4') - -# Include TLV library -include(`common/tlv.m4') - -# Include Token library -include(`sof/tokens.m4') - -# Include DSP configuration -include(`platform/imx/imx8.m4') - -# -# Define the pipelines -# -# PCM0 <----> volume <-----> SAI3 (`CODEC') -# - -dnl PIPELINE_PCM_ADD(pipeline, -dnl pipe id, pcm, max channels, format, -dnl period, priority, core, -dnl pcm_min_rate, pcm_max_rate, pipeline_rate, -dnl time_domain, sched_comp) - -# Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. -# Set 1000us deadline with priority 0 on core 0 -PIPELINE_PCM_ADD(sof/pipe-`PPROC'-playback.m4, - 1, 0, 2, s32le, - 1000, 0, 0, - `RATE', `RATE', `RATE') - -# Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. -# Set 1000us deadline with priority 0 on core 0 -PIPELINE_PCM_ADD(sof/pipe-volume-capture.m4, - 2, 0, 2, s32le, - 1000, 0, 0, - `RATE', `RATE', `RATE') -# -# DAIs configuration -# - -# define STREAM_NAME, based on CODEC name -define(`STREAM_NAME', - `ifelse(CODEC, `wm8960', `wm8960-hifi', - CODEC, `wm8904', `wm8904-hifi', - CODEC, `wm8962', `wm8962', - `fatal_error(`Codec not supported.')')') - -# define DAI BE dai_link name -define(`DAI_BE_NAME', concat(`sai3-', STREAM_NAME)) - -dnl DAI_ADD(pipeline, -dnl pipe id, dai type, dai_index, dai_be, -dnl buffer, periods, format, -dnl period, priority, core, time_domain) - -# playback DAI is SAI3 using 2 periods -# Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-playback.m4, - 1, SAI, 3, DAI_BE_NAME, - PIPELINE_SOURCE_1, 2, s32le, - 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) - -# capture DAI is SAI3 using 2 periods -# Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 -DAI_ADD(sof/pipe-dai-capture.m4, - 2, SAI, 3, DAI_BE_NAME, - PIPELINE_SINK_2, 2, s32le, - 1000, 0, 0) - -# PCM Low Latency, id 0 - -dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) -PCM_DUPLEX_ADD(Port0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) - -dnl DAI_CONFIG(type, idx, link_id, name, sai_config) -DAI_CONFIG(SAI, 3, 0, DAI_BE_NAME, -ifelse( - CODEC, `wm8960', ` - SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), - SAI_CLOCK(bclk, 3072000, codec_master), - SAI_CLOCK(fsync, `RATE', codec_master), - SAI_TDM(2, 32, 3, 3), - SAI_CONFIG_DATA(SAI, 3, 0)))', - CODEC, `wm8904', ` - SAI_CONFIG(I2S, SAI_CLOCK(mclk, 11565177, codec_mclk_in), - SAI_CLOCK(bclk, 1411200, codec_provider), - SAI_CLOCK(fsync, `RATE', codec_provider), - SAI_TDM(2, 32, 3, 3), - SAI_CONFIG_DATA(SAI, 3, 0)))', - CODEC, `wm8962', ` - SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), - SAI_CLOCK(bclk, 3072000, codec_master), - SAI_CLOCK(fsync, `RATE', codec_master), - SAI_TDM(2, 32, 3, 3), - SAI_CONFIG_DATA(SAI, 3, 0)))', - ) diff --git a/tools/topology/topology1/development/sof-imx8mp-src-wm8960.m4 b/tools/topology/topology1/sof-imx93-wm8962.m4 similarity index 80% rename from tools/topology/topology1/development/sof-imx8mp-src-wm8960.m4 rename to tools/topology/topology1/sof-imx93-wm8962.m4 index 454b3329df74..0e99ce292db8 100644 --- a/tools/topology/topology1/development/sof-imx8mp-src-wm8960.m4 +++ b/tools/topology/topology1/sof-imx93-wm8962.m4 @@ -1,5 +1,5 @@ # -# Topology for i.MX8MP board with wm8960 codec +# Topology for i.MX93 board with WM8962 codec # # Include topology builder @@ -22,7 +22,7 @@ include(`platform/imx/imx8.m4') # # Define the pipelines # -# PCM0 <----> SRC <----> volume <-----> SAI3 (wm8960) +# PCM0 <----> volume <-----> SAI3 (WM8962) # dnl PIPELINE_PCM_ADD(pipeline, @@ -33,17 +33,17 @@ dnl time_domain, sched_comp) # Low Latency playback pipeline 1 on PCM 0 using max 2 channels of s32le. # Set 1000us deadline with priority 0 on core 0 -PIPELINE_PCM_ADD(sof/pipe-src-volume-playback.m4, +PIPELINE_PCM_ADD(sof/pipe-`PPROC'-playback.m4, 1, 0, 2, s32le, 1000, 0, 0, - 8000, 96000, 48000) + 48000, 48000, 48000) # Low Latency capture pipeline 2 on PCM 0 using max 2 channels of s32le. # Set 1000us deadline with priority 0 on core 0 -PIPELINE_PCM_ADD(sof/pipe-src-volume-capture.m4, +PIPELINE_PCM_ADD(sof/pipe-`PPROC'-capture.m4, 2, 0, 2, s32le, 1000, 0, 0, - 8000, 96000, 48000) + 48000, 48000, 48000) # # DAIs configuration # @@ -53,17 +53,17 @@ dnl pipe id, dai type, dai_index, dai_be, dnl buffer, periods, format, dnl period, priority, core, time_domain) -# playback DAI is SAI3 using 2 periods +# playback DAI is SAI1 using 2 periods # Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-playback.m4, - 1, SAI, 3, sai3-wm8960-hifi, + 1, SAI, 3, sai3-wm8962, PIPELINE_SOURCE_1, 2, s32le, 1000, 0, 0, SCHEDULE_TIME_DOMAIN_DMA) -# capture DAI is SAI3 using 2 periods +# capture DAI is SAI1 using 2 periods # Buffers use s32le format, with 48 frame per 1000us on core 0 with priority 0 DAI_ADD(sof/pipe-dai-capture.m4, - 2, SAI, 3, sai3-wm8960-hifi, + 2, SAI, 3, sai3-wm8962, PIPELINE_SINK_2, 2, s32le, 1000, 0, 0) @@ -74,7 +74,7 @@ dnl PCM_DUPLEX_ADD(name, pcm_id, playback, capture) PCM_DUPLEX_ADD(Port0, 0, PIPELINE_PCM_1, PIPELINE_PCM_2) dnl DAI_CONFIG(type, idx, link_id, name, sai_config) -DAI_CONFIG(SAI, 3, 0, sai3-wm8960-hifi, +DAI_CONFIG(SAI, 3, 0, sai3-wm8962, SAI_CONFIG(I2S, SAI_CLOCK(mclk, 12288000, codec_mclk_in), SAI_CLOCK(bclk, 3072000, codec_master), SAI_CLOCK(fsync, 48000, codec_master), diff --git a/tools/topology/topology2/avs-tplg/tplg-targets.cmake b/tools/topology/topology2/avs-tplg/tplg-targets.cmake index 63ea74e7e2f1..c89cd2f4e74a 100644 --- a/tools/topology/topology2/avs-tplg/tplg-targets.cmake +++ b/tools/topology/topology2/avs-tplg/tplg-targets.cmake @@ -14,35 +14,31 @@ DEEPBUFFER_FW_DMA_MS=100" "sof-hda-generic\;sof-hda-generic-4ch\;\ HDA_CONFIG=mix,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-4ch.bin,USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100" -# CAVS SDW topology with passthrough pipelines -"cavs-sdw\;cavs-sdw\;DEEPBUFFER_FW_DMA_MS=100,\ -PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-cavs-sdw.bin" # IPC4 topology for TGL rt711 Headset + rt1316 Amplifier + rt714 DMIC -"cavs-sdw\;sof-tgl-rt711-rt1316-rt714\;NUM_SDW_AMPS=2,SDW_DMIC=1,\ +"cavs-sdw\;sof-tgl-rt711-rt1316-rt714\;NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,\ PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-tgl-rt711-rt1316-rt714.bin" -"cavs-sdw\;sof-adl-rt711-l0-rt1316-l12-rt714-l3\;NUM_SDW_AMPS=2,SDW_DMIC=1" +"cavs-sdw\;sof-adl-rt711-l0-rt1316-l12-rt714-l3\;NUM_SDW_AMP_LINKS=2,SDW_DMIC=1" # IPC4 topology for TGL rt711 Headset + rt1308 Amplifier + rt715 DMIC -"cavs-sdw\;sof-tgl-rt715-rt711-rt1308-mono\;NUM_SDW_AMPS=1,SDW_DMIC=1,\ +"cavs-sdw\;sof-tgl-rt715-rt711-rt1308-mono\;NUM_SDW_AMP_LINKS=1,SDW_DMIC=1,\ SDW_JACK_OUT_STREAM=SDW1-Playback,SDW_JACK_IN_STREAM=SDW1-Capture,\ SDW_SPK_STREAM=SDW2-Playback,SDW_DMIC_STREAM=SDW0-Capture,SDW_AMP_FEEDBACK=false,\ PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-tgl-rt715-rt711-rt1308-mono.bin" # IPC4 topology for TGL rt711 Headset + rt1308 Amplifier + PCH DMIC -"cavs-sdw\;sof-tgl-rt711-rt1308-4ch\;NUM_SDW_AMPS=1,NUM_DMICS=4,DMIC0_ID=3,\ +"cavs-sdw\;sof-tgl-rt711-rt1308-4ch\;NUM_SDW_AMP_LINKS=1,NUM_DMICS=4,DMIC0_ID=3,\ DMIC1_ID=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,SDW_AMP_FEEDBACK=false,\ PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-tgl-rt711-rt1308-4ch.bin" +# IPC4 topology for TGL rt712 Headset, Amp and DMIC +"cavs-sdw\;sof-tgl-rt712\;SDW_JACK_OUT_STREAM=SDW0-Playback-SimpleJack,\ +SDW_JACK_IN_STREAM=SDW0-Capture-SimpleJack,SDW_SPK_STREAM=SDW0-Playback-SmartAmp,\ +SDW_DMIC_STREAM=SDW1-Capture-SmartMic,HDMI1_ID=5,HDMI2_ID=6,HDMI3_ID=7,\ +NUM_SDW_AMP_LINKS=1,SDW_AMP_FEEDBACK=false,SDW_DMIC=1,SDW_DMIC_STREAM=SDW1-Capture-SmartMic" + "cavs-sdw\;sof-adl-rt711-4ch\;DEEPBUFFER_FW_DMA_MS=100,NUM_DMICS=4,DMIC0_ID=2,\ DMIC1_ID=3,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,HDMI1_ID=4,HDMI2_ID=5,\ HDMI3_ID=6,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-adl-rt711-4ch.bin" - -# BT offload -"cavs-nocodec-bt\;sof-nocodec-bt\;PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nocodec-bt.bin,\ -PLATFORM=tgl" -# BT offload loopback test topology (lbm) -"cavs-nocodec-bt\;sof-nocodec-bt-lbm\;BT_LOOPBACK_MODE=true,PLATFORM=tgl,\ -PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nocodec-bt-lbm.bin" ) diff --git a/tools/topology/topology2/cavs-mixin-mixout-efx-hda.conf b/tools/topology/topology2/cavs-mixin-mixout-efx-hda.conf index 8f3b96e87a2b..4a7be279a466 100644 --- a/tools/topology/topology2/cavs-mixin-mixout-efx-hda.conf +++ b/tools/topology/topology2/cavs-mixin-mixout-efx-hda.conf @@ -11,7 +11,7 @@ Define { # include deep buffer config if buffer size is in 1 - 1000 ms. IncludeByKey.DEEPBUFFER_FW_DMA_MS{ - "[1-1000]" "platform/intel/deep-buffer.conf" + "([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|1000)" "platform/intel/deep-buffer.conf" } Object.Dai.HDA [ @@ -60,8 +60,9 @@ Object.Pipeline { { index 1 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 } Object.Widget.gain.1 { @@ -75,8 +76,9 @@ Object.Pipeline { host-gateway-capture [ { index 3 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 } } ] @@ -135,6 +137,10 @@ Object.Base.route [ } { source 'copier.HDA.4.1' - sink 'copier.host.3.1' + sink 'host-copier.0.capture' + } + { + source 'host-copier.0.playback' + sink 'gain.1.1' } ] diff --git a/tools/topology/topology2/cavs-mixin-mixout-hda.conf b/tools/topology/topology2/cavs-mixin-mixout-hda.conf index aa00ca621093..2e5ec99d5477 100644 --- a/tools/topology/topology2/cavs-mixin-mixout-hda.conf +++ b/tools/topology/topology2/cavs-mixin-mixout-hda.conf @@ -40,7 +40,7 @@ Object.Pipeline { } Object.Widget.gain.1 { Object.Control.mixer.1 { - name '2 Main Playback Volume' + name 'Post Mixer $ANALOG_PLAYBACK_PCM Volume' } } } @@ -50,13 +50,14 @@ Object.Pipeline { { index 1 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 } Object.Widget.gain.1 { Object.Control.mixer.1 { - name '1 2nd Playback Volume' + name 'Pre Mixer $ANALOG_PLAYBACK_PCM Volume' } } } @@ -65,8 +66,9 @@ Object.Pipeline { host-gateway-capture [ { index 3 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 } } ] @@ -134,6 +136,10 @@ Object.Base.route [ } { source 'eqiir.4.1' - sink 'copier.host.3.1' + sink 'host-copier.0.capture' + } + { + source 'host-copier.0.playback' + sink 'gain.1.1' } ] diff --git a/tools/topology/topology2/cavs-nocodec-bt.conf b/tools/topology/topology2/cavs-nocodec-bt.conf index 33adb22cca52..f027fd97f4e9 100644 --- a/tools/topology/topology2/cavs-nocodec-bt.conf +++ b/tools/topology/topology2/cavs-nocodec-bt.conf @@ -161,8 +161,9 @@ Object.Pipeline { Object.Widget.pipeline.1 { stream_name 'NoCodec-0' } - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name 'SSP0 Playback' + pcm_id 0 } } { @@ -170,8 +171,9 @@ Object.Pipeline { Object.Widget.pipeline.1 { stream_name 'NoCodec-1' } - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name 'SSP1 Playback' + pcm_id 1 } } ] @@ -183,8 +185,9 @@ Object.Pipeline { Object.Widget.pipeline.1 { stream_name 'NoCodec-0' } - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name 'SSP0 Capture' + pcm_id 0 } } { @@ -192,8 +195,9 @@ Object.Pipeline { Object.Widget.pipeline.1 { stream_name 'NoCodec-1' } - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name 'SSP1 Capture' + pcm_id 1 } } ] @@ -291,23 +295,19 @@ Object.PCM.pcm [ Object.Base.route [ { - source "copier.host.1.1" + source "host-copier.0.playback" sink "copier.SSP.2.1" } { - source "copier.host.3.1" + source "host-copier.1.playback" sink "copier.SSP.4.1" } { source "copier.SSP.6.1" - sink "copier.host.5.1" + sink "host-copier.0.capture" } { source "copier.SSP.10.1" - sink "copier.host.9.1" - } - { - source "copier.SSP.12.1" - sink "copier.host.11.1" + sink "host-copier.1.capture" } ] diff --git a/tools/topology/topology2/cavs-nocodec-multicore.conf b/tools/topology/topology2/cavs-nocodec-multicore.conf new file mode 100644 index 000000000000..581126d0c1e6 --- /dev/null +++ b/tools/topology/topology2/cavs-nocodec-multicore.conf @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Define { + MCLK 24576000 + PLATFORM "none" + SSP0_CORE_ID 0 + SSP1_CORE_ID 1 + SSP2_CORE_ID 2 +} + +# override defaults with platform-specific config +IncludeByKey.PLATFORM { + "tgl" "platform/intel/tgl.conf" + "adl" "platform/intel/tgl.conf" + "mtl" "platform/intel/mtl.conf" +} + +# +# List of all DAIs +# +Object.Dai.SSP [ + { + id 0 + dai_index 0 + direction "duplex" + name NoCodec-0 + default_hw_conf_id 0 + sample_bits 32 + quirks "lbm_mode" + io_clk $MCLK + + Object.Base.hw_config.1 { + name "SSP0" + id 0 + bclk_freq 3072000 + tdm_slot_width 32 + # TODO: remove this. Needs alsaptlg change. + Object.Base.link_config.1 { + clock_source 1 + } + } + } + { + id 2 + dai_index 2 + direction "duplex" + name NoCodec-2 + default_hw_conf_id 0 + sample_bits 32 + quirks "lbm_mode" + io_clk $MCLK + + Object.Base.hw_config.1 { + name "SSP2" + id 0 + bclk_freq 3072000 + tdm_slot_width 32 + # TODO: remove this. Needs alsaptlg change. + Object.Base.link_config.1 { + clock_source 1 + } + } + } +] + +# +# Pipeline definitions +# +# PCM0 ---> gain ---> Mixin ---> Mixout ---> gain ---> SSP0 (core SSP0_CORE_ID) +# PCM1 ---> gain ---> Mixin ---> Mixout ---> gain ---> SSP1 (core SSP1_CORE_ID) +# PCM2 ---> gain ---> Mixin ---> Mixout ---> gain ---> SSP2 (core SSP2_CORE_ID) +# SSP0 ---> PCM0 +# SSP1 ---> PCM1 +# SSP2 ---> PCM2 + +# Pipeline ID:1 PCM ID: 0 +Object.Pipeline.host-copier-gain-mixin-playback [ + { + index 1 + + core $SSP0_CORE_ID + Object.Widget.host-copier.1 { + core_id $SSP0_CORE_ID + stream_name 'SSP0 Playback' + pcm_id 0 + } + Object.Widget.gain.1 { + core_id $SSP0_CORE_ID + Object.Control.mixer.1 { + name 'Playback Volume 1' + } + } + } + { + index 5 + + core $SSP2_CORE_ID + Object.Widget.host-copier.1 { + core_id $SSP2_CORE_ID + stream_name 'SSP2 Playback' + pcm_id 2 + } + Object.Widget.gain.1 { + core_id $SSP2_CORE_ID + Object.Control.mixer.1 { + name 'Playback Volume 5' + } + } + Object.Widget.mixin.1 { + core_id $SSP2_CORE_ID + } + } +] + +Object.Pipeline.mixout-gain-dai-copier-playback [ + { + index 14 + + core $SSP0_CORE_ID + Object.Widget.copier.1 { + core_id $SSP0_CORE_ID + dai_index 0 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-0" + node_type $I2S_LINK_OUTPUT_CLASS + } + + Object.Widget.gain.1 { + core_id $SSP0_CORE_ID + Object.Control.mixer.1 { + name 'Main Playback Volume 14' + } + } + } + { + index 6 + + core $SSP2_CORE_ID + Object.Widget.copier.1 { + core_id $SSP2_CORE_ID + dai_index 2 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-2" + node_type $I2S_LINK_OUTPUT_CLASS + } + + Object.Widget.gain.1 { + core_id $SSP2_CORE_ID + Object.Control.mixer.1 { + name 'Main Playback Volume 6' + } + } + Object.Widget.mixout.1 { + core_id $SSP2_CORE_ID + } + } +] + +Object.Pipeline.host-gateway-capture [ + { + index 7 + + Object.Widget.host-copier.1 { + stream_name 'SSP0 Capture' + pcm_id 0 + } + } + { + index 11 + + Object.Widget.host-copier.1 { + stream_name 'SSP2 Capture' + pcm_id 2 + } + } +] + +Object.Pipeline.io-gateway-capture [ + { + index 8 + direction capture + + Object.Widget.copier."1" { + dai_index 1 + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "NoCodec-0" + node_type $I2S_LINK_INPUT_CLASS + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + } + } + { + index 12 + direction capture + + Object.Widget.copier."1" { + dai_index 2 + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "NoCodec-2" + node_type $I2S_LINK_INPUT_CLASS + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + } + } +] + +Object.PCM.pcm [ + { + name "Port0" + id 0 + direction "duplex" + Object.Base.fe_dai.1 { + name "Port0" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "SSP0 Playback" + formats 'S16_LE,S24_LE,S32_LE' + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP0 Capture" + formats 'S16_LE,S24_LE,S32_LE' + } + } + { + name "Port2" + id 2 + direction "duplex" + Object.Base.fe_dai.1 { + name "Port2" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "SSP2 Playback" + formats 'S16_LE,S24_LE,S32_LE' + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP2 Capture" + formats 'S16_LE,S24_LE,S32_LE' + } + } +] + +Object.Base.route [ + { + source "gain.14.1" + sink "copier.SSP.14.1" + } + { + source "mixin.1.1" + sink "mixout.14.1" + } + { + source "gain.6.1" + sink "copier.SSP.6.1" + } + { + source "mixin.5.1" + sink "mixout.6.1" + } + { + source "copier.SSP.8.1" + sink "host-copier.0.capture" + } + { + source "copier.SSP.12.1" + sink "host-copier.2.capture" + } + { + source 'host-copier.0.playback' + sink 'gain.1.1' + } + { + source 'host-copier.2.playback' + sink 'gain.5.1' + } +] + +# There is pinmux conflict between SSP1 and DMIC on MTL RVP, +# so include SSP1 pipelines conditionally. +IncludeByKey.SSP1_ENABLED { + "true" { + Object.Dai.SSP [ + { + id 1 + dai_index 1 + direction "duplex" + name NoCodec-1 + default_hw_conf_id 0 + sample_bits 32 + quirks "lbm_mode" + io_clk $MCLK + + Object.Base.hw_config.1 { + name "SSP1" + id 0 + bclk_freq 3072000 + tdm_slot_width 32 + # TODO: remove this. Needs alsaptlg change. + Object.Base.link_config.1 { + clock_source 1 + } + } + } + ] + + Object.Pipeline.host-copier-gain-mixin-playback [ + { + index 3 + + core $SSP1_CORE_ID + Object.Widget.host-copier.1 { + core_id $SSP1_CORE_ID + stream_name 'SSP1 Playback' + pcm_id 1 + } + Object.Widget.gain.1 { + core_id $SSP1_CORE_ID + Object.Control.mixer.1 { + name 'Playback Volume 3' + } + } + Object.Widget.mixin.1 { + core_id $SSP1_CORE_ID + } + } + ] + + Object.Pipeline.mixout-gain-dai-copier-playback [ + { + index 4 + + core $SSP1_CORE_ID + Object.Widget.copier.1 { + core_id $SSP1_CORE_ID + dai_index 1 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_OUTPUT_CLASS + } + + Object.Widget.gain.1 { + core_id $SSP1_CORE_ID + Object.Control.mixer.1 { + name 'Main Playback Volume 4' + } + } + Object.Widget.mixout.1 { + core_id $SSP1_CORE_ID + } + } + ] + + Object.Pipeline.host-gateway-capture [ + { + index 9 + + Object.Widget.host-copier.1 { + stream_name 'SSP1 Capture' + pcm_id 1 + } + } + ] + + Object.Pipeline.io-gateway-capture [ + { + index 10 + direction capture + + Object.Widget.copier."1" { + dai_index 1 + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_INPUT_CLASS + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + } + } + ] + + Object.PCM.pcm [ + { + name "Port1" + id 1 + direction "duplex" + Object.Base.fe_dai.1 { + name "Port1" + } + + Object.PCM.pcm_caps.1 { + direction "playback" + name "SSP1 Playback" + formats 'S16_LE,S24_LE,S32_LE' + } + + Object.PCM.pcm_caps.2 { + direction "capture" + name "SSP1 Capture" + formats 'S16_LE,S24_LE,S32_LE' + } + } + ] + + Object.Base.route [ + { + source "mixin.3.1" + sink "mixout.4.1" + } + { + source "gain.4.1" + sink "copier.SSP.4.1" + } + { + source "copier.SSP.10.1" + sink "host-copier.1.capture" + } + { + source 'host-copier.1.playback' + sink 'gain.3.1' + } + ] + } +} diff --git a/tools/topology/topology2/cavs-nocodec.conf b/tools/topology/topology2/cavs-nocodec.conf index dd0c7dde8802..ea30b2607f9f 100644 --- a/tools/topology/topology2/cavs-nocodec.conf +++ b/tools/topology/topology2/cavs-nocodec.conf @@ -12,7 +12,9 @@ + + @@ -79,6 +81,7 @@ Define { SSP0_MIXER_SINK_2 'mixout.16.1' SSP0_MIXER_SOURCE_3 'mixin.21.1' SSP1_ENABLED "true" + PASSTHROUGH "false" } # override defaults with platform-specific config @@ -86,6 +89,7 @@ IncludeByKey.PLATFORM { "tgl" "platform/intel/tgl.conf" "adl" "platform/intel/tgl.conf" "mtl" "platform/intel/mtl.conf" + "lnl" "platform/intel/mtl.conf" } # include DMIC config if needed. @@ -94,8 +98,12 @@ IncludeByKey.NUM_DMICS { } # include deep buffer config if buffer size is in 1 - 1000 ms. -IncludeByKey.DEEPBUFFER_FW_DMA_MS{ - "[1-1000]" "platform/intel/deep-buffer.conf" +IncludeByKey.PASSTHROUGH { +"false" { + IncludeByKey.DEEPBUFFER_FW_DMA_MS{ + "([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|1000)" "platform/intel/deep-buffer.conf" + } + } } # @@ -160,250 +168,443 @@ Object.Dai.SSP [ # SSP1 ---> PCM1 # SSP2 ---> PCM2 -# Pipeline ID:1 PCM ID: 0 -Object.Pipeline.host-copier-gain-mixin-playback [ - { - index 1 +IncludeByKey.PASSTHROUGH { +"false" { + Object.Pipeline.host-copier-gain-mixin-playback [ + { + index 1 - Object.Widget.copier.1 { - stream_name 'SSP0 Playback' - } - Object.Widget.gain.1 { - Object.Control.mixer.1 { - name 'Playback Volume 1' + Object.Widget.host-copier.1 { + stream_name 'SSP0 Playback' + pcm_id 0 + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Playback Volume 1' + } + } } - } - } - { - index 5 + { + index 5 - Object.Widget.copier.1 { - stream_name 'SSP2 Playback' - } - Object.Widget.gain.1 { - Object.Control.mixer.1 { - name 'Playback Volume 5' + Object.Widget.host-copier.1 { + stream_name 'SSP2 Playback' + pcm_id 2 + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Playback Volume 5' + } + } } - } - } -] + ] -Object.Pipeline.mixout-gain-smart-amp-dai-copier-playback [ - { - index 2 - - Object.Widget.copier.1 { - dai_index 0 - dai_type "SSP" - copier_type "SSP" - stream_name "NoCodec-0" - node_type $I2S_LINK_OUTPUT_CLASS - } + Object.Pipeline.mixout-gain-smart-amp-dai-copier-playback [ + { + index 2 - Object.Widget.gain.1 { - Object.Control.mixer.1 { - name 'Main Playback Volume 2' - } - } + Object.Widget.copier.1 { + dai_index 0 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-0" + node_type $I2S_LINK_OUTPUT_CLASS + } - Object.Widget.smart_amp.1 { + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Main Playback Volume 2' + } + } - Object.Base.input_pin_binding.1 { - input_pin_binding_name "gain.2.1" - } + Object.Widget.smart_amp.1 { - Object.Base.input_pin_binding.2 { - input_pin_binding_name "copier.SSP.8.1" - } + Object.Base.input_pin_binding.1 { + input_pin_binding_name "gain.2.1" + } - Object.Control.bytes."1" { - name smart_amp_init + Object.Base.input_pin_binding.2 { + input_pin_binding_name "copier.SSP.8.1" + } + + Object.Control.bytes."1" { + name smart_amp_init + } + } } - } - } -] + ] -Object.Pipeline.mixout-gain-dai-copier-playback [ - { - index 6 - - Object.Widget.copier.1 { - dai_index 2 - dai_type "SSP" - copier_type "SSP" - stream_name "NoCodec-2" - node_type $I2S_LINK_OUTPUT_CLASS - } + Object.Pipeline.mixout-gain-dai-copier-playback [ + { + index 6 + + Object.Widget.copier.1 { + dai_index 2 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-2" + node_type $I2S_LINK_OUTPUT_CLASS + } - Object.Widget.gain.1 { - Object.Control.mixer.1 { - name 'Main Playback Volume 6' + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Main Playback Volume 6' + } + } } - } - } -] + ] -Object.Pipeline.gain-copier-capture [ - { - index 7 + Object.Pipeline.gain-copier-capture [ + { + index 7 - Object.Widget.copier.1 { - stream_name 'SSP0 Capture' - } - Object.Widget.gain.1 { - Object.Control.mixer.1 { - name 'Main Capture Volume 1' + Object.Widget.host-copier.1 { + stream_name 'SSP0 Capture' + pcm_id 7 + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Main Capture Volume 1' + } + } } - } - } - { - index 17 - format s32le - Object.Widget.copier.1 { - stream_name 'SSP0-1 Capture' - } - Object.Widget.gain.1 { - Object.Control.mixer.1 { - name 'Main Capture Volume 2' + { + index 17 + format s32le + Object.Widget.host-copier.1 { + stream_name 'SSP0-1 Capture' + pcm_id 12 + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Main Capture Volume 2' + } + } } - } - } -] + ] -Object.Pipeline.gain-module-copier [ - { - index 19 - direction "capture" - Object.Widget.pipeline.1 { - stream_name $DMIC0_DAI_COPIER - } - Object.Widget.module-copier.1 { - stream_name 'Gain Capture 19' - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 - } - } - Object.Widget.gain.1 { - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 + Object.Pipeline.gain-module-copier [ + { + index 19 + direction "capture" + Object.Widget.pipeline.1 { + stream_name $DMIC0_DAI_COPIER + } + Object.Widget.module-copier.1 { + stream_name 'Gain Capture 19' + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + Object.Widget.gain.1 { + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + Object.Control.mixer.1 { + name 'Main Capture Volume 3' + } + } } - Object.Control.mixer.1 { - name 'Main Capture Volume 3' + ] + + Object.Pipeline.dai-copier-gain-module-copier-capture [ + { + index 8 + Object.Widget.copier."1" { + dai_index 0 + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "NoCodec-0" + node_type $I2S_LINK_INPUT_CLASS + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + + Object.Base.output_pin_binding.1 { + output_pin_binding_name "gain.8.1" + } + + Object.Base.output_pin_binding.2 { + output_pin_binding_name "smart_amp.2.1" + } + } + + Object.Widget.module-copier."2" { + stream_name "NoCodec-0" + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Host Capture Volume' + } + } } - } + ] } -] +"true" { + Object.Pipeline.io-gateway [ + { + index 2 + direction playback -Object.Pipeline.dai-copier-gain-module-copier-capture [ - { - index 8 - Object.Widget.copier."1" { - dai_index 0 - dai_type "SSP" - type dai_out - copier_type "SSP" - stream_name "NoCodec-0" - node_type $I2S_LINK_INPUT_CLASS - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 + Object.Widget.copier.1 { + dai_index 0 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-0" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } } + { + index 6 + direction playback - Object.Base.output_pin_binding.1 { - output_pin_binding_name "gain.8.1" + Object.Widget.copier.1 { + dai_index 2 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-2" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } } + ] - Object.Base.output_pin_binding.2 { - output_pin_binding_name "smart_amp.2.1" + Object.Pipeline.host-gateway-playback [ + { + index 1 + Object.Widget.host-copier.1 { + stream_name 'SSP0 Playback' + pcm_id 0 + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } } - } + { + index 5 + Object.Widget.host-copier.1 { + stream_name 'SSP2 Playback' + pcm_id 2 + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] - Object.Widget.module-copier."2" { - stream_name "NoCodec-0" - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 + Object.Pipeline.host-gateway-capture [ + { + index 7 + + Object.Widget.host-copier.1 { + stream_name 'SSP0 Capture' + pcm_id 0 + } } - } - Object.Widget.gain.1 { - Object.Control.mixer.1 { - name 'Host Capture Volume' + ] + + Object.Pipeline.io-gateway-capture [ + { + index 8 + direction capture + + Object.Widget.copier."1" { + dai_index 0 + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "NoCodec-0" + node_type $I2S_LINK_INPUT_CLASS + num_input_audio_formats 1 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 1 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } } - } + ] } -] +} Object.Pipeline.host-gateway-capture [ { index 11 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name 'SSP2 Capture' + pcm_id 2 } } ] Object.Pipeline.io-gateway-capture [ - { - index 10 - direction capture - - Object.Widget.copier."1" { - dai_index 1 - dai_type "SSP" - type dai_out - copier_type "SSP" - stream_name "NoCodec-1" - node_type $I2S_LINK_INPUT_CLASS - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - } - } { index 12 direction capture @@ -425,122 +626,124 @@ Object.Pipeline.io-gateway-capture [ } ] -Object.Pipeline.gain-capture [ - { - format $FORMAT - index 18 - Object.Widget.pipeline.1 { - stream_name "DMIC0 Raw" - } - Object.Widget.copier.1 { - stream_name "Gain Capture 18" - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 - } - } - Object.Widget.gain.1 { - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 - } - Object.Control.mixer.1 { - name 'Capture Raw Volume 1' - } - } - } - { - format $FORMAT - index 20 - Object.Widget.pipeline.1 { - stream_name "DMIC0 Raw 2" - } - Object.Widget.copier.1 { - stream_name "Gain Capture 20" - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 - } - } - Object.Widget.gain.1 { - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 +IncludeByKey.PASSTHROUGH { +"false" { + Object.Pipeline.gain-capture [ + { + format $FORMAT + index 18 + Object.Widget.pipeline.1 { + stream_name "DMIC0 Raw" + } + Object.Widget.host-copier.1 { + stream_name "Gain Capture 18" + pcm_id 27 + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + Object.Widget.gain.1 { + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + Object.Control.mixer.1 { + name 'Capture Raw Volume 1' + } + } } - Object.Control.mixer.1 { - name 'Capture Raw Volume 2' + { + format $FORMAT + index 20 + Object.Widget.pipeline.1 { + stream_name "DMIC0 Raw 2" + } + Object.Widget.host-copier.1 { + stream_name "Gain Capture 20" + pcm_id 28 + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + Object.Widget.gain.1 { + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + Object.Control.mixer.1 { + name 'Capture Raw Volume 2' + } + } } - } + ] } -] +} Object.PCM.pcm [ { @@ -563,18 +766,6 @@ Object.PCM.pcm [ formats 'S16_LE,S24_LE,S32_LE' } } - { - name "ssp-capture" - id 12 - direction "capture" - Object.Base.fe_dai.1 { - name "ssp-capture" - } - Object.PCM.pcm_caps.1 { - name "SSP0-1 Capture" - formats 'S16_LE,S24_LE,S32_LE' - } - } { name "Port2" id 2 @@ -595,96 +786,165 @@ Object.PCM.pcm [ formats 'S16_LE,S24_LE,S32_LE' } } - { - name "DMIC0 Raw" - id 27 - direction "capture" - Object.Base.fe_dai."DMIC0 Raw" {} - - Object.PCM.pcm_caps."capture" { - name "Gain Capture 18" - # only 32-bit capture supported now - formats 'S32_LE' - channels_min $NUM_DMICS - channels_max $NUM_DMICS - } - } - { - name "DMIC0 Raw 2" - id 28 - direction "capture" - Object.Base.fe_dai."DMIC0 Raw 2" {} - - Object.PCM.pcm_caps."capture" { - name "Gain Capture 20" - # only 32-bit capture supported now - formats 'S32_LE' - channels_min $NUM_DMICS - channels_max $NUM_DMICS - } - } ] -Object.Base.route [ - { - source "smart_amp.2.1" - sink "copier.SSP.2.1" - } - { - source "gain.6.1" - sink "copier.SSP.6.1" - } - { - source "mixin.5.1" - sink "mixout.6.1" - } - { - source "copier.SSP.8.1" - sink "gain.8.1" +IncludeByKey.PASSTHROUGH { +"false" { + Object.PCM.pcm [ + { + name "ssp-capture" + id 12 + direction "capture" + Object.Base.fe_dai.1 { + name "ssp-capture" + } + Object.PCM.pcm_caps.1 { + name "SSP0-1 Capture" + formats 'S16_LE,S24_LE,S32_LE' + } + } + { + name "DMIC0 Raw" + id 27 + direction "capture" + Object.Base.fe_dai."DMIC0 Raw" {} + + Object.PCM.pcm_caps."capture" { + name "Gain Capture 18" + # only 32-bit capture supported now + formats 'S32_LE' + channels_min $NUM_DMICS + channels_max $NUM_DMICS + } + } + { + name "DMIC0 Raw 2" + id 28 + direction "capture" + Object.Base.fe_dai."DMIC0 Raw 2" {} + + Object.PCM.pcm_caps."capture" { + name "Gain Capture 20" + # only 32-bit capture supported now + formats 'S32_LE' + channels_min $NUM_DMICS + channels_max $NUM_DMICS + } + } + ] } +} + +Object.Base.route [ { source "copier.SSP.12.1" - sink "copier.host.11.1" - } - { - source "module-copier.8.2" - sink "module-copier.7.2" - } - { - source "module-copier.8.2" - sink "module-copier.17.2" - } - { - source module-copier.14.2 - sink gain.19.1 + sink "host-copier.2.capture" } - { - source module-copier.19.1 - sink gain.18.1 - } - { - source module-copier.19.1 - sink gain.20.1 +] + +IncludeByKey.PASSTHROUGH { +"false" { + Object.Base.route [ + { + source "smart_amp.2.1" + sink "copier.SSP.2.1" + } + { + source "gain.6.1" + sink "copier.SSP.6.1" + } + { + source "mixin.5.1" + sink "mixout.6.1" + } + { + source "copier.SSP.8.1" + sink "gain.8.1" + } + { + source "module-copier.8.2" + sink "module-copier.7.2" + } + { + source "module-copier.8.2" + sink "module-copier.17.2" + } + { + source module-copier.14.2 + sink gain.19.1 + } + { + source module-copier.19.1 + sink gain.18.1 + } + { + source module-copier.19.1 + sink gain.20.1 + } + { + source "copier.SSP.8.1" + sink "smart_amp.2.1" + } + { + source 'host-copier.0.playback' + sink 'gain.1.1' + } + { + source 'host-copier.2.playback' + sink 'gain.5.1' + } + { + source "gain.18.1" + sink "host-copier.27.capture" + } + { + source "gain.20.1" + sink "host-copier.28.capture" + } + { + source "gain.7.1" + sink "host-copier.7.capture" + } + { + source "gain.17.1" + sink "host-copier.12.capture" + } + ] } - { - source "copier.SSP.8.1" - sink "smart_amp.2.1" +"true" { + Object.Base.route [ + { + source "copier.SSP.8.1" + sink "host-copier.0.capture" + } + { + source "host-copier.0.playback" + sink "copier.SSP.2.1" + } + { + source "host-copier.2.playback" + sink "copier.SSP.6.1" + } + ] } -] +} -IncludeByKey.SSP0_MIXER_2LEVEL { - "0" { - Object.Base.route [ - { - source $SSP0_MIXER_SOURCE_1 - sink $SSP0_MIXER_SINK_1 +IncludeByKey.PASSTHROUGH { +"false" { + IncludeByKey.SSP0_MIXER_2LEVEL { + "0" { + Object.Base.route [ + { + source $SSP0_MIXER_SOURCE_1 + sink $SSP0_MIXER_SINK_1 + } + ] } - ] + "1" "platform/intel/nocodec-ssp0-2level.conf" } - "1" "platform/intel/nocodec-ssp0-2level.conf" + } } - # There is pinmux conflict between SSP1 and DMIC on MTL RVP, # so include SSP1 pipelines conditionally. IncludeByKey.SSP1_ENABLED { @@ -713,36 +973,23 @@ IncludeByKey.SSP1_ENABLED { } ] - Object.Pipeline.host-copier-gain-mixin-playback [ + Object.Pipeline.io-gateway-capture [ { - index 3 + index 10 + direction capture - Object.Widget.copier.1 { - stream_name 'SSP1 Playback' - } - Object.Widget.gain.1 { - Object.Control.mixer.1 { - name 'Playback Volume 3' - } - } - } - ] - - Object.Pipeline.mixout-gain-dai-copier-playback [ - { - index 4 - - Object.Widget.copier.1 { - dai_index 1 - dai_type "SSP" - copier_type "SSP" - stream_name "NoCodec-1" - node_type $I2S_LINK_OUTPUT_CLASS - } - - Object.Widget.gain.1 { - Object.Control.mixer.1 { - name 'Main Playback Volume 4' + Object.Widget.copier."1" { + dai_index 1 + dai_type "SSP" + type dai_out + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_INPUT_CLASS + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 } } } @@ -752,12 +999,138 @@ IncludeByKey.SSP1_ENABLED { { index 9 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name 'SSP1 Capture' + pcm_id 1 } } ] + IncludeByKey.PASSTHROUGH { + "false" { + Object.Pipeline.host-copier-gain-mixin-playback [ + { + index 3 + + Object.Widget.host-copier.1 { + stream_name 'SSP1 Playback' + pcm_id 1 + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Playback Volume 3' + } + } + } + ] + + Object.Pipeline.mixout-gain-dai-copier-playback [ + { + index 4 + + Object.Widget.copier.1 { + dai_index 1 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_OUTPUT_CLASS + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'Main Playback Volume 4' + } + } + } + ] + } + "true" { + Object.Pipeline.io-gateway [ + { + index 4 + direction playback + + Object.Widget.copier.1 { + dai_index 0 + dai_type "SSP" + copier_type "SSP" + stream_name "NoCodec-1" + node_type $I2S_LINK_OUTPUT_CLASS + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + Object.Pipeline.host-gateway-playback [ + { + index 3 + Object.Widget.host-copier.1 { + stream_name 'SSP1 Playback' + pcm_id 1 + num_input_audio_formats 3 + Object.Base.input_audio_format [ + { + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + num_output_audio_formats 3 + Object.Base.output_audio_format [ + { + out_bit_depth 16 + out_valid_bit_depth 16 + } + { + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + } + ] + } + } + Object.PCM.pcm [ { name "Port1" @@ -781,18 +1154,36 @@ IncludeByKey.SSP1_ENABLED { } ] - Object.Base.route [ - { - source "mixin.3.1" - sink "mixout.4.1" + IncludeByKey.PASSTHROUGH { + "false" { + Object.Base.route [ + { + source "mixin.3.1" + sink "mixout.4.1" + } + { + source "gain.4.1" + sink "copier.SSP.4.1" + } + { + source 'host-copier.1.playback' + sink 'gain.3.1' + } + ] } - { - source "gain.4.1" - sink "copier.SSP.4.1" + "true" { + Object.Base.route [ + { + source "host-copier.1.playback" + sink "copier.SSP.4.1" + } + ] } + } + Object.Base.route [ { source "copier.SSP.10.1" - sink "copier.host.9.1" + sink "host-copier.1.capture" } ] } diff --git a/tools/topology/topology2/cavs-rt5682.conf b/tools/topology/topology2/cavs-rt5682.conf index 545dacab36eb..970a8d742436 100644 --- a/tools/topology/topology2/cavs-rt5682.conf +++ b/tools/topology/topology2/cavs-rt5682.conf @@ -21,6 +21,8 @@ + + @@ -41,6 +43,10 @@ + + + + Define { MCLK 24576000 @@ -91,6 +97,8 @@ Define { BT_PB_HOST_PIPELINE_SINK "copier.SSP.10.1" BT_PB_DAI_PIPELINE_SRC "copier.host.9.1" BT_PB_PIPELINE_STREAM_NAME "copier.SSP.10.1" + GOOGLE_RTC_AEC_SUPPORT 0 + GOOGLE_RTC_AEC_REF_SOURCE 'module-copier.8.2' } # override defaults with platform-specific config @@ -110,13 +118,18 @@ IncludeByKey.NUM_HDMIS { # include deep buffer config if buffer size is in 1 - 1000 ms. IncludeByKey.DEEPBUFFER_FW_DMA_MS{ - "[1-1000]" "platform/intel/deep-buffer.conf" + "([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|1000)" "platform/intel/deep-buffer.conf" } IncludeByKey.INCLUDE_ECHO_REF { "true" "platform/intel/speaker-echo-ref.conf" } +# enable GOOGLE RTC AEC if needed +IncludeByKey.GOOGLE_RTC_AEC_SUPPORT { + "[1]" "platform/intel/google-rtc-aec-reference.conf" +} + # # List of all DAIs # @@ -188,8 +201,9 @@ Object.Pipeline { { index 1 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name '$HEADSET_PLAYBACK_PCM_STREAM_NAME' + pcm_id 0 } Object.Widget.gain.1 { Object.Control.mixer.1 { @@ -200,8 +214,9 @@ Object.Pipeline { { index 3 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name '$SPEAKER_PLAYBACK_PCM_STREAM_NAME' + pcm_id 1 } Object.Widget.gain.1 { Object.Control.mixer.1 { @@ -221,14 +236,6 @@ Object.Pipeline { copier_type "SSP" stream_name "$HEADSET_CODEC_NAME" node_type $I2S_LINK_OUTPUT_CLASS - - # override for 24-bit - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 32 - } } Object.Widget.gain.1 { @@ -260,8 +267,9 @@ Object.Pipeline { { index 5 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name '$HEADSET_CAPTURE_PCM_STREAM_NAME' + pcm_id 0 } } ] @@ -287,63 +295,6 @@ Object.Pipeline { } } ] - - gain-capture [ - { - format $FORMAT - index 16 - - Object.Widget.pipeline.1 { - stream_name "DMIC Raw" - } - Object.Widget.copier.1 { - stream_name "DMIC Raw" - num_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_QUATRO - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_QUATRO - out_ch_map $CHANNEL_MAP_3_POINT_1 - } - } - Object.Widget.gain.1 { - num_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_QUATRO - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_QUATRO - out_ch_map $CHANNEL_MAP_3_POINT_1 - } - Object.Control.mixer.1 { - name 'Capture Raw Volume 1' - } - } - } - ] } Object.PCM.pcm [ @@ -380,20 +331,6 @@ Object.PCM.pcm [ formats 'S16_LE,S24_LE,S32_LE' } } - { - name "DMIC Raw" - id 18 - direction "capture" - Object.Base.fe_dai."DMIC Raw" {} - - Object.PCM.pcm_caps."capture" { - name "DMIC Raw" - # only 32-bit capture supported now - formats 'S32_LE' - channels_min $NUM_DMICS - channels_max $NUM_DMICS - } - } ] Object.Base.route [ @@ -415,10 +352,14 @@ Object.Base.route [ } { source "copier.SSP.6.1" - sink "copier.host.5.1" + sink "host-copier.0.capture" } { - source "module-copier.14.2" - sink "gain.16.1" + source "host-copier.0.playback" + sink "gain.1.1" + } + { + source "host-copier.1.playback" + sink "gain.3.1" } ] diff --git a/tools/topology/topology2/cavs-sdw-src-gain-mixin.conf b/tools/topology/topology2/cavs-sdw-src-gain-mixin.conf index 5786ae6d70f4..df6e1cc2517d 100644 --- a/tools/topology/topology2/cavs-sdw-src-gain-mixin.conf +++ b/tools/topology/topology2/cavs-sdw-src-gain-mixin.conf @@ -11,7 +11,7 @@ - + @@ -80,7 +80,10 @@ Object.Pipeline { { index 1 - Object.Widget.copier.1.stream_name "Gain Playback 0" + Object.Widget.host-copier.1 { + stream_name "Gain Playback 0" + pcm_id 0 + } Object.Widget.gain.1{ Object.Control.mixer.1 { name 'Src Playback Volume' @@ -90,14 +93,12 @@ Object.Pipeline { } ] - mixout-gain-dai-copier-playback [ + mixout-gain-alh-dai-copier-playback [ { index 2 - Object.Widget.copier.1 { + Object.Widget.alh-copier.1 { stream_name $SDW_PLAYBACK_PCM - dai_type "ALH" - copier_type "ALH" type "dai_in" node_type $ALH_LINK_OUTPUT_CLASS } @@ -114,27 +115,53 @@ Object.Pipeline { { index 4 - Object.Widget.copier.1.stream_name "Passthrough Capture 0" - Object.Widget.copier.1.Object.Base.audio_format.1 { - # 32 -> 16 bits conversion is done here, - # so in_bit_depth is 32 (and out_bit_depth is 16). - in_bit_depth 32 + Object.Widget.host-copier.1 { + stream_name "Passthrough Capture 0" + pcm_id 1 + Object.Base.audio_format.1 { + # 32 -> 16 bits conversion is done here, + # so in_bit_depth is 32 (and out_bit_depth is 16). + in_bit_depth 32 + } } } ] +} - io-gateway-capture [ +# Capture pipeline widgets +Object.Widget { + alh-copier [ { + stream_name $SDW_CAPTURE_PCM direction "capture" - index 3 - copier_type "ALH" - Object.Widget.copier.1 { - stream_name $SDW_CAPTURE_PCM - dai_type "ALH" - copier_type "ALH" - type "dai_out" - node_type $ALH_LINK_INPUT_CLASS - } + type "dai_out" + index 3 + node_type $ALH_LINK_INPUT_CLASS + num_input_audio_formats 1 + num_output_audio_formats 1 + num_output_pins 1 + + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + ] + + pipeline [ + { + index 3 + priority 0 + lp_mode 0 + dynamic_pipeline 1 } ] } @@ -177,10 +204,14 @@ Object.Base.route [ } { source 'gain.2.1' - sink 'copier.ALH.2.1' + sink 'alh-copier.$SDW_PLAYBACK_PCM.0' } { - source "copier.ALH.3.1" - sink "copier.host.4.1" + source "alh-copier.$SDW_CAPTURE_PCM.0" + sink "host-copier.1.capture" + } + { + source 'host-copier.0.playback' + sink 'src.1.1' } ] diff --git a/tools/topology/topology2/cavs-sdw.conf b/tools/topology/topology2/cavs-sdw.conf index 865a1a7c384f..b8f1d4245f53 100644 --- a/tools/topology/topology2/cavs-sdw.conf +++ b/tools/topology/topology2/cavs-sdw.conf @@ -11,7 +11,7 @@ - + @@ -33,10 +33,13 @@ + + + @@ -67,8 +70,9 @@ Define { SDW_JACK_IN_STREAM 'SDW0-Capture' SDW_JACK_OUT_BE_ID 0 SDW_JACK_IN_BE_ID 1 - NUM_SDW_AMPS 0 + NUM_SDW_AMP_LINKS 0 SDW_DMIC 0 + SDW_JACK true } # override defaults with platform-specific config @@ -90,12 +94,7 @@ IncludeByKey.NUM_HDMIS { "[3-4]" "platform/intel/hdmi-generic.conf" } -# include deep buffer config if buffer size is in 1 - 1000 ms. -IncludeByKey.DEEPBUFFER_FW_DMA_MS{ - "[1-1000]" "platform/intel/deep-buffer.conf" -} - -IncludeByKey.NUM_SDW_AMPS { +IncludeByKey.NUM_SDW_AMP_LINKS { "[1-2]" "platform/intel/sdw-amp-generic.conf" } @@ -103,159 +102,7 @@ IncludeByKey.SDW_DMIC { "1" "platform/intel/sdw-dmic-generic.conf" } -# -# List of all DAIs -# -#ALH Index: 0, Direction: duplex -Object.Dai.ALH [ - { - dai_index 0 - id $SDW_JACK_OUT_BE_ID - direction "playback" - name $SDW_JACK_OUT_STREAM - default_hw_conf_id 0 - rate 48000 - channels 2 - - Object.Base.hw_config.1 { - id 0 - name "ALH2" - } - } - { - dai_index 10 - id $SDW_JACK_IN_BE_ID - direction "capture" - name $SDW_JACK_IN_STREAM - default_hw_conf_id 1 - rate 48000 - channels 2 - - Object.Base.hw_config.1 { - id 1 - name "ALH3" - } - } -] - -# -# Pipeline definitions -# - -# Pipeline ID:1 PCM ID: 0 -Object.Pipeline { - host-copier-gain-mixin-playback [ - { - index 0 - - Object.Widget.copier.1 { - stream_name "volume playback 0" - } - Object.Widget.gain.1 { - Object.Control.mixer.1 { - name '1 Playback Volume 0' - } - } - } - ] - - mixout-gain-dai-copier-playback [ - { - index 1 - - Object.Widget.copier.1 { - stream_name $SDW_JACK_OUT_STREAM - dai_type "ALH" - copier_type "ALH" - node_type $ALH_LINK_OUTPUT_CLASS - } - Object.Widget.gain.1 { - Object.Control.mixer.1 { - name '2 Main Playback Volume' - } - } - } - ] - - host-gateway-capture [ - { - index 10 - - Object.Widget.copier.1.stream_name "Passthrough Capture 0" - Object.Widget.copier.1.Object.Base.audio_format.1 { - # 32/32 -> 16/16 bits conversion is done here - in_bit_depth 32 - in_valid_bit_depth 32 - } - } - ] - - highpass-capture-be [ - { - direction "capture" - index 11 - copier_type "ALH" - - Object.Widget.copier.1 { - stream_name $SDW_JACK_IN_STREAM - dai_type "ALH" - copier_type "ALH" - type "dai_out" - node_type $ALH_LINK_INPUT_CLASS - } - Object.Widget.eqiir.1 { - Object.Control.bytes."1" { - name '4 Main capture Iir Eq' - } - } - } - ] +IncludeByKey.SDW_JACK { +"true" "platform/intel/sdw-jack-generic.conf" } -Object.PCM.pcm [ - { - name "Jack out" - id 0 - direction "playback" - Object.Base.fe_dai.1 { - name "Jack out" - } - - Object.PCM.pcm_caps.1 { - name "volume playback 0" - formats 'S16_LE,S32_LE' - } - } - { - name "Jack in" - id 1 - direction "capture" - Object.Base.fe_dai.1 { - name "Jack in" - } - - Object.PCM.pcm_caps.1 { - name "Passthrough Capture 0" - formats 'S16_LE,S32_LE' - } - } -] - -Object.Base.route [ - { - source "gain.1.1" - sink "copier.ALH.1.1" - } - { - source "mixin.0.1" - sink "mixout.1.1" - } - { - source "copier.ALH.11.1" - sink "eqiir.11.1" - } - { - source "eqiir.11.1" - sink "copier.host.10.1" - } -] diff --git a/tools/topology/topology2/cavs-src-mixin-mixout-hda.conf b/tools/topology/topology2/cavs-src-mixin-mixout-hda.conf index dfda6d5132ca..bebca860f66d 100644 --- a/tools/topology/topology2/cavs-src-mixin-mixout-hda.conf +++ b/tools/topology/topology2/cavs-src-mixin-mixout-hda.conf @@ -11,7 +11,7 @@ Define { # include deep buffer config if buffer size is in 1 - 1000 ms. IncludeByKey.DEEPBUFFER_FW_DMA_MS{ - "[1-1000]" "platform/intel/deep-buffer.conf" + "([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|1000)" "platform/intel/deep-buffer.conf" } Object.Dai.HDA [ @@ -50,8 +50,9 @@ Object.Pipeline { { index 1 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $ANALOG_PLAYBACK_PCM + pcm_id 0 } Object.Widget.src.1 { @@ -68,8 +69,9 @@ Object.Pipeline { host-gateway-capture [ { index 3 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $ANALOG_CAPTURE_PCM + pcm_id 0 } } ] @@ -130,6 +132,10 @@ Object.Base.route [ } { source 'copier.HDA.4.1' - sink 'copier.host.3.1' + sink 'host-copier.0.capture' + } + { + source 'host-copier.0.playback' + sink 'gain.1.1' } ] diff --git a/tools/topology/topology2/development/tplg-targets.cmake b/tools/topology/topology2/development/tplg-targets.cmake index faed8382d4a1..f0bb239421e9 100644 --- a/tools/topology/topology2/development/tplg-targets.cmake +++ b/tools/topology/topology2/development/tplg-targets.cmake @@ -28,9 +28,28 @@ PLATFORM=adl" # SSP topology for MTL "cavs-nocodec\;sof-mtl-nocodec\;PLATFORM=mtl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ -PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-nocodec.bin,DEEPBUFFER_FW_DMA_MS=100" +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-nocodec.bin,DEEPBUFFER_FW_DMA_MS=100,\ +DEEPBUFFER_D0I3_COMPATIBLE=true" "cavs-nocodec\;sof-mtl-nocodec-ssp0-ssp2\;PLATFORM=mtl,NUM_DMICS=2,SSP1_ENABLED=false,\ -PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-nocodec.bin,DEEPBUFFER_FW_DMA_MS=100" +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-nocodec.bin,DEEPBUFFER_FW_DMA_MS=100,\ +DEEPBUFFER_D0I3_COMPATIBLE=true" + +"cavs-nocodec-multicore\;sof-mtl-nocodec-multicore\;PLATFORM=mtl,SSP1_ENABLED=true,SSP0_CORE_ID=0,\ +SSP1_CORE_ID=1,SSP2_CORE_ID=2,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-nocodec.bin" + +# SSP topology for LNL FPGA with lower DMIC IO clock of 19.2MHz, 2ch PDM1 enabled +"cavs-nocodec\;sof-lnl-nocodec-fpga-2ch-pdm1\;PLATFORM=lnl,NUM_DMICS=2,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,PDM0_MIC_A_ENABLE=0,PDM0_MIC_B_ENABLE=0,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-lnl-nocodec-fpga-2ch-pdm1.bin,PASSTHROUGH=true,DMIC_IO_CLK=19200000" + +# SSP topology for LNL FPGA with lower DMIC IO clock of 19.2MHz, 2ch PDM0 enabled +"cavs-nocodec\;sof-lnl-nocodec-fpga-2ch-pdm0\;PLATFORM=lnl,NUM_DMICS=2,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-lnl-nocodec-fpga-2ch-pdm0.bin,PASSTHROUGH=true,DMIC_IO_CLK=19200000" + +# SSP topology for LNL FPGA with lower DMIC IO clock of 19.2MHz, 4ch both PDM0 and PDM1 enabled +"cavs-nocodec\;sof-lnl-nocodec-fpga-4ch\;PLATFORM=lnl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ +PDM1_MIC_B_ENABLE=1,PREPROCESS_PLUGINS=nhlt,\ +NHLT_BIN=nhlt-sof-lnl-nocodec-fpga-4ch.bin,PASSTHROUGH=true,DMIC_IO_CLK=19200000" # CAVS HDA topology with mixer-based efx eq pipelines for HDA and passthrough pipelines for HDMI "sof-hda-generic\;sof-hda-efx-generic\;HDA_CONFIG=efx,USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100,\ @@ -44,5 +63,19 @@ PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-efx-generic-4ch.bin,USE_CHAIN_DMA= DEEPBUFFER_FW_DMA_MS=100,EFX_FIR_PARAMS=passthrough,EFX_IIR_PARAMS=passthrough" # CAVS HDA topology with gain and SRC before mixin for HDA and passthrough pipelines for HDMI "sof-hda-generic\;sof-hda-src-generic\;HDA_CONFIG=src,USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100" + +# BT offload for tgl +"cavs-nocodec-bt\;sof-nocodec-bt-tgl\;PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nocodec-bt-tgl.bin,\ +PLATFORM=tgl" +# BT offload loopback test topology (lbm) for tgl +"cavs-nocodec-bt\;sof-nocodec-bt-tgl-lbm\;BT_LOOPBACK_MODE=true,PLATFORM=tgl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nocodec-bt-tgl-lbm.bin" + +# BT offload for mtl +"cavs-nocodec-bt\;sof-nocodec-bt-mtl\;PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nocodec-bt-mtl.bin,\ +PLATFORM=mtl" +# BT offload loopback test topology (lbm) for mtl +"cavs-nocodec-bt\;sof-nocodec-bt-mtl-lbm\;BT_LOOPBACK_MODE=true,PLATFORM=mtl,\ +PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-nocodec-bt-mtl-lbm.bin" ) diff --git a/tools/topology/topology2/include/common/input_audio_format.conf b/tools/topology/topology2/include/common/input_audio_format.conf index 0dd7c56e2a97..c45f36505a27 100644 --- a/tools/topology/topology2/include/common/input_audio_format.conf +++ b/tools/topology/topology2/include/common/input_audio_format.conf @@ -15,7 +15,7 @@ Class.Base."input_audio_format" { DefineAttribute."instance" { } - DefineAttribute."pin_index" { + DefineAttribute."input_pin_index" { # Token set reference name token_ref "sof_tkn_cavs_audio_format.word" } diff --git a/tools/topology/topology2/include/common/output_audio_format.conf b/tools/topology/topology2/include/common/output_audio_format.conf index a04cf2e07f0f..c1779b191735 100644 --- a/tools/topology/topology2/include/common/output_audio_format.conf +++ b/tools/topology/topology2/include/common/output_audio_format.conf @@ -15,7 +15,7 @@ Class.Base."output_audio_format" { DefineAttribute."instance" { } - DefineAttribute."pin_index" { + DefineAttribute."output_pin_index" { # Token set reference name token_ref "sof_tkn_cavs_audio_format.word" } diff --git a/tools/topology/topology2/include/common/tokens.conf b/tools/topology/topology2/include/common/tokens.conf index f0c9c4345850..61aa8c2f506f 100644 --- a/tools/topology/topology2/include/common/tokens.conf +++ b/tools/topology/topology2/include/common/tokens.conf @@ -5,8 +5,8 @@ Object.Base.VendorToken { "1" { name "sof_tkn_comp" - period_sink_count 400 - period_source_count 401 + period_sink_count 400 # not used with IPC4 + period_source_count 401 # not used with IPC4 format 402 # Token retired with ABI 3.2, do not use for new capabilities preload_count 403 @@ -15,7 +15,7 @@ Object.Base.VendorToken { # Tokens added with ABI 4.0 cpc 406 is_pages 409 - num_audio_formats 410 + num_audio_formats 410 #deprecated num_input_pins 411 num_output_pins 412 # The token for input/output pin binding, it specifies @@ -156,7 +156,7 @@ Object.Base.VendorToken { in_interleaving_style 1906 in_fmt_cfg 1907 in_sample_type 1908 - pin_index 1909 + input_pin_index 1909 # tokens up to 1929 reserved for future use out_rate 1930 out_bit_depth 1931 @@ -167,6 +167,7 @@ Object.Base.VendorToken { out_interleaving_style 1936 out_fmt_cfg 1937 out_sample_type 1938 + output_pin_index 1939 # tokens up to 1969 reserved for future use ibs 1970 obs 1971 diff --git a/tools/topology/topology2/include/common/vendor-token.conf b/tools/topology/topology2/include/common/vendor-token.conf index ce498e327113..722cd7867c96 100644 --- a/tools/topology/topology2/include/common/vendor-token.conf +++ b/tools/topology/topology2/include/common/vendor-token.conf @@ -5,8 +5,6 @@ # Usage: this component can be used by instantiating it in the parent object. i.e. # # Object.Base.VendorToken. "sof_tkn_comp" { -# period_sink_count 400 -# period_source_count 401 # # Token retired with ABI 3.2, do not use for new capabilities # preload_count 403 # core_id 404 diff --git a/tools/topology/topology2/include/components/alh-dai-copier.conf b/tools/topology/topology2/include/components/alh-dai-copier.conf new file mode 100644 index 000000000000..b1eaab2a17fd --- /dev/null +++ b/tools/topology/topology2/include/components/alh-dai-copier.conf @@ -0,0 +1,143 @@ +# +# ALH DAI gateway copier +# +# ALH DAI copier widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.alh-copier.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.alh-copier."N" { +# dai_index 0 +# stream_name "SDW1-Playback" +# } +# +# Where N is the unique instance number for the alh-copier object within the same alsaconf node. + +Class.Widget."alh-copier" { + # + # Pipeline ID for the alh-copier object + # + DefineAttribute."index" {} + + # DAI index: this is always 0 when there is no aggregation. + DefineAttribute."dai_index" { + token_ref "sof_tkn_dai.word" + } + + # + # alh-copier object instance + # + DefineAttribute."instance" {} + + #include common component definition + + + # + # alh-copier component UUID + # + DefineAttribute."uuid" { + type "string" + # Token set reference name and type + token_ref "sof_tkn_comp.uuid" + } + + # + # Bespoke Attribute Definitions for alh-copier + # + + DefineAttribute."dai_type" { + type "string" + token_ref "sof_tkn_dai.string" + } + + DefineAttribute."direction" { + type "string" + token_ref "sof_tkn_dai.word" + constraints { + !valid_values [ + "playback" + "capture" + ] + !tuple_values [ + 0 + 1 + ] + } + } + + # + # cycles per chunk processed + # + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "sof_tkn_comp.word" + } + + DefineAttribute."bss_size" {} + + DefineAttribute."is_pages" { + # Token set reference name and type + token_ref "sof_tkn_comp.word" + } + + DefineAttribute."node_type" { + # Token set reference name and type + token_ref "sof_tkn_copier.word" + constraints { + !valid_values [ + $ALH_LINK_OUTPUT_CLASS # ALH link output, legacy for SNDW (DSP ->) + $ALH_LINK_INPUT_CLASS # ALH link input, legacy for SNDW (DSP <-) + ] + } + } + + attributes { + # + # The alh-copier widget name would be constructed using the stream_name, + # direction and dai_index attributes. For ex: "alh-copier.SDW1-Playback.0". + # + !constructor [ + "stream_name" + "dai_index" + ] + + # + # mandatory attributes that must be provided when the alh-copier class is + # instantiated + # + !mandatory [ + "no_pm" + "num_input_audio_formats" + "num_output_audio_formats" + "node_type" + ] + + # + # immutable attributes cannot be modified in the object instance + # num_input_audio_formats for capture and num_output_formats for playback are + # mandatory even though the num_input_pins/num_output_pins are 0 because + # these are used to set the DMA buffer format. + # + !immutable [ + "uuid" + "dai_type" + ] + + unique "instance" + } + + # + # Default attributes for alh-copier + # + #UUID: 9BA00C83-CA12-4A83-943C-1FA2E82F9DDA + uuid "83:0c:a0:9b:12:CA:83:4a:94:3c:1f:a2:e8:2f:9d:da" + no_pm "true" + core_id 0 + cpc 1647 + bss_size 280 + dai_type "ALH" + dai_index 0 + + # math expression for computing is_pages + is_pages "$[(($bss_size + 4095) & -4095) / 4096]" +} diff --git a/tools/topology/topology2/include/components/asrc.conf b/tools/topology/topology2/include/components/asrc.conf index 4034290a3a34..9ea02c887c92 100644 --- a/tools/topology/topology2/include/components/asrc.conf +++ b/tools/topology/topology2/include/components/asrc.conf @@ -6,8 +6,6 @@ # Usage: this component can be used by instantiating it in the parent object. i.e. # # Object.Widget.asrc."N" { -# period_sink_count 2 -# period_source_count 2 # format "s24le" # rate_out 48000 # asynchronous_mode 1 diff --git a/tools/topology/topology2/include/components/copier.conf b/tools/topology/topology2/include/components/copier.conf index 53039e7332bf..9e46da0e1242 100644 --- a/tools/topology/topology2/include/components/copier.conf +++ b/tools/topology/topology2/include/components/copier.conf @@ -51,9 +51,7 @@ Class.Widget."copier" { constraints { !valid_values [ "HDA" - "host" "SSP" - "ALH" "DMIC" ] } @@ -67,7 +65,6 @@ Class.Widget."copier" { "SSP" "DMIC" "HDA" - "ALH" ] } } @@ -95,11 +92,6 @@ Class.Widget."copier" { token_ref "sof_tkn_comp.word" } - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - DefineAttribute."bss_size" {} DefineAttribute."is_pages" { @@ -112,21 +104,12 @@ Class.Widget."copier" { token_ref "sof_tkn_copier.word" constraints { !valid_values [ - $HDA_HOST_OUTPUT_CLASS # HD/A host output (-> DSP) - $HDA_HOST_INPUT_CLASS # HD/A host input (<- DSP) - $HDA_HOST_INOUT_CLASS # HD/A host input/output (rsvd for future use) $HDA_LINK_OUTPUT_CLASS # HD/A link output (DSP ->) $HDA_LINK_INPUT_CLASS # HD/A link input (DSP <-) $HDA_LINK_INOUT_CLASS # HD/A link input/output (rsvd for future use) $DMIC_LINK_INPUT_CLASS # DMIC link input (DSP <-) $I2S_LINK_OUTPUT_CLASS # I2S link output (DSP ->) $I2S_LINK_INPUT_CLASS # I2S link input (DSP <-) - $ALH_LINK_OUTPUT_CLASS # ALH link output, legacy for SNDW (DSP ->) - $ALH_LINK_INPUT_CLASS # ALH link input, legacy for SNDW (DSP <-) - $ALH_SNDWIRE_STREAM_LINK_OUTPUT_CLASS # SNDW link output (DSP ->) - $ALH_SNDWIRE_STREAM_LINK_INPUT_CLASS # SNDW link input (DSP <-) - $ALH_UAOL_STREAM_LINK_OUTPUT_CLASS # UAOL link output (DSP ->) - $ALH_UAOL_STREAM_LINK_INPUT_CLASS # UAOL link input (DSP <-) $IPC_OUTPUT_CLASS # IPC output (DSP ->) $IPC_INPUT_CLASS # IPC input (DSP <-) $I2S_MULTILINK_OUTPUT_CLASS # I2S Multi gtw output (DSP ->) @@ -138,14 +121,6 @@ Class.Widget."copier" { } } - # - # Deep buffer size in ms. Applicable only for host copiers - # - DefineAttribute."deep_buffer_dma_ms" { - # Token set reference name and type - token_ref "sof_tkn_copier.word" - } - attributes { # # The copier widget name would be constructed using the copier type, index and diff --git a/tools/topology/topology2/include/components/dai.conf b/tools/topology/topology2/include/components/dai.conf index f500b14ec0d1..51d33dec9efe 100644 --- a/tools/topology/topology2/include/components/dai.conf +++ b/tools/topology/topology2/include/components/dai.conf @@ -6,8 +6,6 @@ # Object.Widget.dai."playback" { # dai_type SSP # index 1 -# period_sink_count 2 -# period_source_count 0 # type dai_in # } # @@ -15,8 +13,6 @@ # Object.Widget.dai."capture" { # dai_type SSP # index 2 -# period_sink_count 0 -# period_source_count 2 # type dai_out # } # @@ -104,8 +100,6 @@ Class.Widget."dai" { "stream_name" "format" "index" - "period_sink_count" - "period_source_count" "format" ] diff --git a/tools/topology/topology2/include/components/eqfir.conf b/tools/topology/topology2/include/components/eqfir.conf index 60d2a6005c74..e294f9e3ba15 100644 --- a/tools/topology/topology2/include/components/eqfir.conf +++ b/tools/topology/topology2/include/components/eqfir.conf @@ -6,8 +6,6 @@ # Usage: this component can be used by declaring in the parent object. i.e. # # Object.Widget.eqfir."N" { -# period_sink_count 2 -# period_source_count 2 # index 1 # } # } @@ -38,11 +36,6 @@ Class.Widget."eqfir" { token_ref "sof_tkn_comp.uuid" } - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - attributes { !constructor [ "index" @@ -71,8 +64,6 @@ Class.Widget."eqfir" { uuid "e7:0c:a9:43:a5:f3:df:41:ac:06:ba:98:65:1a:e6:a3" type "effect" no_pm "true" - period_sink_count 2 - period_source_count 2 core_id 0 num_input_pins 1 num_output_pins 1 diff --git a/tools/topology/topology2/include/components/eqiir.conf b/tools/topology/topology2/include/components/eqiir.conf index 4b28e9ae81f3..3a0b20247d3b 100644 --- a/tools/topology/topology2/include/components/eqiir.conf +++ b/tools/topology/topology2/include/components/eqiir.conf @@ -6,8 +6,6 @@ # Usage: this component can be used by declaring in the parent object. i.e. # # Object.Widget.eqiir."N" { -# period_sink_count 2 -# period_source_count 2 # index 1 # } # } @@ -38,11 +36,6 @@ Class.Widget."eqiir" { token_ref "sof_tkn_comp.uuid" } - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - attributes { !constructor [ "index" @@ -71,8 +64,6 @@ Class.Widget."eqiir" { uuid "e6:c0:50:51:f9:27:c8:4e:83:51:c7:05:b6:42:d1:2f" type "effect" no_pm "true" - period_sink_count 2 - period_source_count 2 core_id 0 num_input_pins 1 num_output_pins 1 diff --git a/tools/topology/topology2/include/components/gain.conf b/tools/topology/topology2/include/components/gain.conf index 455fea23ba5e..931998c598a5 100644 --- a/tools/topology/topology2/include/components/gain.conf +++ b/tools/topology/topology2/include/components/gain.conf @@ -77,11 +77,6 @@ Class.Widget."gain" { token_ref "sof_tkn_gain.word" } - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - # Attribute categories attributes { # @@ -165,8 +160,6 @@ Class.Widget."gain" { uuid "A8:A9:BC:61:D0:18:18:4A:8E:7B:26:39:21:98:04:B7" no_pm "true" cpc 10183 - period_sink_count 2 - period_source_count 2 curve_type "fade" curve_duration 200000 # 20 ms init_value 0x7fffffff diff --git a/tools/topology/topology2/include/components/google-rtc-aec.conf b/tools/topology/topology2/include/components/google-rtc-aec.conf new file mode 100644 index 000000000000..f4c27ece570c --- /dev/null +++ b/tools/topology/topology2/include/components/google-rtc-aec.conf @@ -0,0 +1,139 @@ +# +# Common widget google-rtc-aec +# +# A generic google-rtc-aec widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.google-rtc-aec.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.google-rtc-aec."N" { +# index 1 +# type "effect" +# } +# +# Where N is the unique instance number for the google-rtc-aec object within the same alsaconf node. +Define { + AEC_UUID "a6:a0:80:b7:9f:26:6f:46:b4:77:23:df:a0:5a:f7:58" +} + +Class.Widget."google-rtc-aec" { + # + # Pipeline ID for the google-rtc-aec widget object + # + DefineAttribute."index" {} + + # + # google-rtc-aec object instance + # + DefineAttribute."instance" {} + + #include common component definition + + + DefineAttribute."num_audio_formats" { + # Token set reference name and type + token_ref "sof_tkn_comp.word" + } + + # + # google-rtc-aec widget UUID + # + DefineAttribute."uuid" { + type "string" + # Token set reference name and type + token_ref "sof_tkn_comp.uuid" + } + + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "sof_tkn_comp.word" + } + + DefineAttribute."is_pages" { + # Token set reference name and type + token_ref "sof_tkn_comp.word" + } + + # Attribute categories + attributes { + # + # The google-rtc-aec widget name would be constructed using the index and instance attributes. + # For ex: "google-rtc-aec.1.1" or "google-rtc-aec.10.2" etc. + # + !constructor [ + "index" + "instance" + ] + + # + # mandatory attributes that must be provided when the class is instantiated + # + !mandatory [ + "no_pm" + "uuid" + "process_type" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + "type" + ] + + # + # deprecated attributes should not be added in the object instance + # + !deprecated [ + "preload_count" + ] + + # + # google-rtc-aec widget objects instantiated within the same alsaconf node must have unique + # instance attribute + # + unique "instance" + } + + num_audio_formats 2 + num_input_audio_formats 2 + num_output_audio_formats 1 + # pin0 is the data captured by DMIC and pin1 is the ref data from playback stream + Object.Base.input_audio_format { + 1 { + pin_index 0 + in_bit_depth 16 + in_valid_bit_depth 16 + out_bit_depth 16 + out_valid_bit_depth 16 + } + 2 { + pin_index 1 + in_bit_depth 16 + in_valid_bit_depth 16 + out_bit_depth 16 + out_valid_bit_depth 16 + } + } + + Object.Base.output_audio_format { + 1 { + in_bit_depth 16 + in_valid_bit_depth 16 + out_bit_depth 16 + out_valid_bit_depth 16 + } + } + + # Default attribute values for google-rtc-aec widget + # UUID: B780A0A6-269F-466F-B477-23DFA05AF758 + uuid $AEC_UUID + type "effect" + no_pm "true" + core_id 0 + cpc 5000 + is_pages 1 + num_input_pins 2 + num_output_pins 1 +} diff --git a/tools/topology/topology2/include/components/google-rtc-aec/rtc-aec-blob.conf b/tools/topology/topology2/include/components/google-rtc-aec/rtc-aec-blob.conf new file mode 100644 index 000000000000..f31ed7a0a747 --- /dev/null +++ b/tools/topology/topology2/include/components/google-rtc-aec/rtc-aec-blob.conf @@ -0,0 +1,19 @@ +# aec blob data + +Object.Base.data."google-rtc-aec_blob" { + bytes " + 0x53, 0x4f, 0x46, 0x34, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x80, 0xbb, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, + + 0x80, 0xbb, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x10, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00" +} diff --git a/tools/topology/topology2/include/components/host-copier.conf b/tools/topology/topology2/include/components/host-copier.conf new file mode 100644 index 000000000000..51b952f07f56 --- /dev/null +++ b/tools/topology/topology2/include/components/host-copier.conf @@ -0,0 +1,138 @@ +# +# Host gateway copier widget +# +# A host gateway copier widget. All attributes defined herein are namespaced +# by alsatplg to "Object.Widget.host-copier.N.attribute_name" +# +# Usage: this component can be used by instantiating it in the parent object. i.e. +# +# Object.Widget.host-copier."N" { +# pcm_id 1 +# } +# +# Where N is the unique instance number for the host-copier object within the same alsaconf node. + +Class.Widget."host-copier" { + # + # Pipeline ID for the copier object + # + DefineAttribute."index" {} + + /* PCM ID that the host-copier is bound with */ + DefineAttribute."pcm_id" {} + + # + # Copier object instance + # + DefineAttribute."instance" {} + + #include common component definition + + + # + # host-copier component UUID + # + DefineAttribute."uuid" { + type "string" + # Token set reference name and type + token_ref "sof_tkn_comp.uuid" + } + + # + # Bespoke Attribute Definitions for host copiers + # + + DefineAttribute."direction" { + type "string" + token_ref "sof_tkn_dai.word" + constraints { + !valid_values [ + "playback" + "capture" + ] + !tuple_values [ + 0 + 1 + ] + } + } + + # + # cycles per chunk processed + # + DefineAttribute."cpc" { + # Token set reference name and type + token_ref "sof_tkn_comp.word" + } + + DefineAttribute."bss_size" {} + + DefineAttribute."is_pages" { + # Token set reference name and type + token_ref "sof_tkn_comp.word" + } + + DefineAttribute."node_type" { + # Token set reference name and type + token_ref "sof_tkn_copier.word" + constraints { + !valid_values [ + $HDA_HOST_OUTPUT_CLASS # HD/A host output (-> DSP) + $HDA_HOST_INPUT_CLASS # HD/A host input (<- DSP) + $HDA_HOST_INOUT_CLASS # HD/A host input/output (rsvd for future use) + ] + } + } + + # + # Deep buffer size in ms. Applicable only for host copiers + # + DefineAttribute."deep_buffer_dma_ms" { + # Token set reference name and type + token_ref "sof_tkn_copier.word" + } + + attributes { + # + # The host copier widget name would be constructed using the copier pcm_id and + # direction. For ex: "host-copier.1.playback". + # + !constructor [ + "pcm_id" + "direction" + ] + + # + # mandatory attributes that must be provided when the buffer class is instantiated. + # num_input_audio_formats for playback and num_output_formats for capture are + # mandatory even though the num_input_pins/num_output_pins are 0 because + # these are used to set the DMA buffer format. + !mandatory [ + "num_input_audio_formats" + "num_output_audio_formats" + "node_type" + ] + + # + # immutable attributes cannot be modified in the object instance + # + !immutable [ + "uuid" + ] + + unique "instance" + } + + # + # Default attributes for Copier + # + #UUID: 9BA00C83-CA12-4A83-943C-1FA2E82F9DDA + uuid "83:0c:a0:9b:12:CA:83:4a:94:3c:1f:a2:e8:2f:9d:da" + no_pm "true" + core_id 0 + cpc 1647 + bss_size 280 + + # math expression for computing is_pages + is_pages "$[(($bss_size + 4095) & -4095) / 4096]" +} diff --git a/tools/topology/topology2/include/components/host.conf b/tools/topology/topology2/include/components/host.conf index fd38a0e29dac..8b8cf36acf11 100644 --- a/tools/topology/topology2/include/components/host.conf +++ b/tools/topology/topology2/include/components/host.conf @@ -6,16 +6,12 @@ # For playback: # Object.Widget.host."playback" { # index 3 -# period_sink_count 2 -# period_source_count 0 # type aif_in # } # # For Capture: # Object.Widget.host."capture" { # index 4 -# period_sink_count 0 -# period_source_count 2 # type aif_out # } @@ -112,6 +108,4 @@ Class.Widget."host" { # uuid "0c:10:9d:8b:78:6d:8f:41:90:a3:e0:e8:05:d0:85:2b" no_pm "true" - period_sink_count 0 - period_source_count 2 } diff --git a/tools/topology/topology2/include/components/kpb.conf b/tools/topology/topology2/include/components/kpb.conf index b017ff7897cb..a1b25a2aabb5 100644 --- a/tools/topology/topology2/include/components/kpb.conf +++ b/tools/topology/topology2/include/components/kpb.conf @@ -28,11 +28,6 @@ Class.Widget."kpb" { token_ref "sof_tkn_comp.word" } - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - #include common component definition @@ -78,7 +73,6 @@ Class.Widget."kpb" { # type "effect" - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 diff --git a/tools/topology/topology2/include/components/micsel.conf b/tools/topology/topology2/include/components/micsel.conf index e45c24d13d18..f81d0b8c65c3 100644 --- a/tools/topology/topology2/include/components/micsel.conf +++ b/tools/topology/topology2/include/components/micsel.conf @@ -28,11 +28,6 @@ Class.Widget."micsel" { token_ref "sof_tkn_comp.word" } - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - #include common component definition @@ -78,7 +73,6 @@ Class.Widget."micsel" { # type "effect" - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 #UUID: 32FE92C1-1E17-4FC2-9758-C7F3542E980A diff --git a/tools/topology/topology2/include/components/mixin.conf b/tools/topology/topology2/include/components/mixin.conf index b491d7f006ce..e43e54062243 100644 --- a/tools/topology/topology2/include/components/mixin.conf +++ b/tools/topology/topology2/include/components/mixin.conf @@ -44,11 +44,6 @@ Class.Widget."mixin" { token_ref "sof_tkn_comp.word" } - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - #include common component definition @@ -100,21 +95,17 @@ Class.Widget."mixin" { } # Only 32-bit depth format is supported by mixin - num_audio_formats 2 + num_input_audio_formats 1 + num_output_audio_formats 1 # 32-bit 48KHz 2ch - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.2 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] # # Default attributes for mixin @@ -129,6 +120,5 @@ Class.Widget."mixin" { cpc 910 num_input_pins 1 num_output_pins 3 - num_input_audio_formats 2 - num_output_audio_formats 2 + } diff --git a/tools/topology/topology2/include/components/mixout.conf b/tools/topology/topology2/include/components/mixout.conf index 7f77c7f37294..d6fdf989bd55 100644 --- a/tools/topology/topology2/include/components/mixout.conf +++ b/tools/topology/topology2/include/components/mixout.conf @@ -44,11 +44,6 @@ Class.Widget."mixout" { token_ref "sof_tkn_comp.word" } - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - #include common component definition @@ -100,23 +95,17 @@ Class.Widget."mixout" { } # Only 32-bit depth format is supported by mixout - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 + num_input_audio_formats 1 + num_output_audio_formats 1 # 32-bit 48KHz 2ch - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.2 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] # # Default attributes for mixout diff --git a/tools/topology/topology2/include/components/module-copier.conf b/tools/topology/topology2/include/components/module-copier.conf index b8765155c99a..d8eb2f9c2679 100644 --- a/tools/topology/topology2/include/components/module-copier.conf +++ b/tools/topology/topology2/include/components/module-copier.conf @@ -48,11 +48,6 @@ Class.Widget."module-copier" { token_ref "sof_tkn_comp.word" } - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - DefineAttribute."bss_size" {} DefineAttribute."is_pages" { diff --git a/tools/topology/topology2/include/components/muxdemux.conf b/tools/topology/topology2/include/components/muxdemux.conf index a2f6f3a4dd11..c762f89d5f3a 100644 --- a/tools/topology/topology2/include/components/muxdemux.conf +++ b/tools/topology/topology2/include/components/muxdemux.conf @@ -7,8 +7,6 @@ # Object.Widget { # muxdemux."N" { # index 3 -# period_sink_count 2 -# period_source_count 2 # format "s24le" # } # } @@ -70,8 +68,6 @@ Class.Widget."muxdemux" { # Default attribute values for muxdemux widget # uuid "68:68:b2:c4:30:14:0e:47:a0:89:15:d1:c7:7f:85:1a" - period_source_count 2 - period_sink_count 2 process_type "DEMUX" widget_type "effect" no_pm "true" diff --git a/tools/topology/topology2/include/components/smart_amp.conf b/tools/topology/topology2/include/components/smart_amp.conf index baf0c2ed97fc..0f36fe66f420 100644 --- a/tools/topology/topology2/include/components/smart_amp.conf +++ b/tools/topology/topology2/include/components/smart_amp.conf @@ -28,11 +28,6 @@ Class.Widget."smart_amp" { #include common component definition - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - # # smart_amp widget UUID # diff --git a/tools/topology/topology2/include/components/src.conf b/tools/topology/topology2/include/components/src.conf index 597bb6716bc0..a1ab81b019d3 100644 --- a/tools/topology/topology2/include/components/src.conf +++ b/tools/topology/topology2/include/components/src.conf @@ -6,8 +6,6 @@ # Usage: this component can be used by instantiating it in the parent object. i.e. # # Object.Widget.src."N" { -# period_sink_count 2 -# period_source_count 2 # format "s24le" # rate_out 48000 # } @@ -37,11 +35,6 @@ Class.Widget."src" { token_ref "sof_tkn_comp.uuid" } - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - # # Bespoke attributes for SRC # @@ -101,8 +94,6 @@ Class.Widget."src" { type "src" uuid "8d:b2:1b:e6:9a:14:1f:4c:b7:09:46:82:3e:f5:f5:ae" no_pm "true" - period_sink_count 2 - period_source_count 2 core_id 0 num_input_pins 1 num_output_pins 1 diff --git a/tools/topology/topology2/include/components/src_format.conf b/tools/topology/topology2/include/components/src_format.conf index b26dbf3c624b..6fc582f0cf0b 100644 --- a/tools/topology/topology2/include/components/src_format.conf +++ b/tools/topology/topology2/include/components/src_format.conf @@ -1,370 +1,238 @@ #src format array - num_audio_formats 42 num_input_audio_formats 42 - num_output_audio_formats 42 - # 8khz input - Object.Base.audio_format.1 { - in_rate 8000 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.2 { - in_rate 8000 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.3{ - in_rate 8000 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - - # 11.025 khz input - Object.Base.audio_format.4 { - in_rate 11025 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - # for 11.025k, 22.05k, 44.1k, 88.2k and 176.4k, extra 4 sample size is needed - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - Object.Base.audio_format.5 { - in_rate 11025 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - Object.Base.audio_format.6{ - in_rate 11025 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - # 12khz input - Object.Base.audio_format.7 { - in_rate 12000 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.8 { - in_rate 12000 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.9{ - in_rate 12000 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - - # 16khz input - Object.Base.audio_format.10 { - in_rate 16000 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.11 { - in_rate 16000 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.12{ - in_rate 16000 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - - # 22.05khz input - Object.Base.audio_format.13 { - in_rate 22050 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - Object.Base.audio_format.14 { - in_rate 22050 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - Object.Base.audio_format.15{ - in_rate 22050 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - - # 24khz input - Object.Base.audio_format.16 { - in_rate 24000 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.17 { - in_rate 24000 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.18{ - in_rate 24000 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - - # 32khz input - Object.Base.audio_format.19 { - in_rate 32000 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.20 { - in_rate 32000 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.21 { - in_rate 32000 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - - # 44.1khz input - Object.Base.audio_format.22 { - in_rate 44100 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - Object.Base.audio_format.23 { - in_rate 44100 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - Object.Base.audio_format.24{ - in_rate 44100 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - # 48khz input - Object.Base.audio_format.25 { - in_rate 48000 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.26 { - in_rate 48000 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.27 { - in_rate 48000 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - - # 64khz input - Object.Base.audio_format.28 { - in_rate 64000 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.29 { - in_rate 64000 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.30 { - in_rate 64000 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - # 88.2khz input - Object.Base.audio_format.31 { - in_rate 88200 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - Object.Base.audio_format.32 { - in_rate 88200 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - Object.Base.audio_format.33 { - in_rate 88200 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - # 96khz input - Object.Base.audio_format.34 { - in_rate 96000 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.35 { - in_rate 96000 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.36 { - in_rate 96000 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - - # 176.4khz input - Object.Base.audio_format.37 { - in_rate 176400 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - Object.Base.audio_format.38 { - in_rate 176400 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - Object.Base.audio_format.39 { - in_rate 176400 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - obs "$[($out_channels * (($[($out_rate + 999)] / 1000) + 4)) * ($out_bit_depth / 8)]" - } - - # 192khz input - Object.Base.audio_format.40 { - in_rate 192000 - in_bit_depth 16 - in_valid_bit_depth 16 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.41 { - in_rate 192000 - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.42 { - in_rate 192000 - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } + Object.Base.input_audio_format [ + # 8khz input + { + in_rate 8000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 8000 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 11.025 khz input + { + in_rate 11025 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 11025 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 11025 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 12khz input + { + in_rate 12000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 12000 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 12000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 16khz input + { + in_rate 16000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 16000 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 16000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 22.05khz input + { + in_rate 22050 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 22050 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 22050 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 24khz input + { + in_rate 24000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 24000 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 24000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 32khz input + { + in_rate 32000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 32000 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 32000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 44.1khz input + { + in_rate 44100 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 44100 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 44100 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 48khz input + { + in_rate 48000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 48000 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 48000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 64khz input + { + in_rate 64000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 64000 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 64000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 88.2khz input + { + in_rate 88200 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 88200 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 88200 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 96khz input + { + in_rate 96000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 96000 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 96000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 176.4khz input + { + in_rate 176400 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 176400 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 176400 + in_bit_depth 32 + in_valid_bit_depth 32 + } + # 192khz input + { + in_rate 192000 + in_bit_depth 16 + in_valid_bit_depth 16 + } + { + in_rate 192000 + in_bit_depth 32 + in_valid_bit_depth 24 + } + { + in_rate 192000 + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + + num_output_audio_formats 1 + + Object.Base.output_audio_format [ + { + out_rate 48000 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] diff --git a/tools/topology/topology2/include/components/src_passthrough_format.conf b/tools/topology/topology2/include/components/src_passthrough_format.conf index 49c2355b57cd..898a6adbbebf 100644 --- a/tools/topology/topology2/include/components/src_passthrough_format.conf +++ b/tools/topology/topology2/include/components/src_passthrough_format.conf @@ -1,5 +1,4 @@ #src format array - num_audio_formats 42 num_input_audio_formats 42 num_output_audio_formats 42 diff --git a/tools/topology/topology2/include/components/volume.conf b/tools/topology/topology2/include/components/volume.conf index f83e0d081889..0ed26801e421 100644 --- a/tools/topology/topology2/include/components/volume.conf +++ b/tools/topology/topology2/include/components/volume.conf @@ -174,8 +174,6 @@ Class.Widget."pga" { type "pga" uuid "7e:67:7e:b7:f4:5f:88:41:af:14:fb:a8:bd:bf:86:82" no_pm "true" - period_sink_count 2 - period_source_count 2 ramp_step_type "linear" ramp_step_ms 400 } diff --git a/tools/topology/topology2/include/components/widget-common.conf b/tools/topology/topology2/include/components/widget-common.conf index 17978c56e444..ee40ad6156f3 100644 --- a/tools/topology/topology2/include/components/widget-common.conf +++ b/tools/topology/topology2/include/components/widget-common.conf @@ -47,18 +47,6 @@ DefineAttribute.event_flags {} # Attributes with a "token_ref" value will be added to widget's private data # -# number of sink periods -DefineAttribute."period_sink_count" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" -} - -# number of source periods -DefineAttribute."period_source_count" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" -} - # widget format DefineAttribute."format" { type "string" diff --git a/tools/topology/topology2/include/components/wov.conf b/tools/topology/topology2/include/components/wov.conf index f9a7f078aeb8..747e3031ff38 100644 --- a/tools/topology/topology2/include/components/wov.conf +++ b/tools/topology/topology2/include/components/wov.conf @@ -30,11 +30,6 @@ Class.Widget."wov" { token_ref "sof_tkn_comp.word" } - DefineAttribute."num_audio_formats" { - # Token set reference name and type - token_ref "sof_tkn_comp.word" - } - #include common component definition @@ -112,7 +107,6 @@ Class.Widget."wov" { # Default attributes for wov # type "effect" - num_audio_formats 1 no_pm "true" core_id 0 num_input_pins 1 diff --git a/tools/topology/topology2/include/dais/ssp.conf b/tools/topology/topology2/include/dais/ssp.conf index 673b4d3dcfd9..287342b4c96f 100644 --- a/tools/topology/topology2/include/dais/ssp.conf +++ b/tools/topology/topology2/include/dais/ssp.conf @@ -16,12 +16,8 @@ # tdm_slot_width 25 # } # Object.dai."playback" { -# period_source_count 2 -# period_sink_count 0 # } # Object.dai."capture" { -# period_source_count 0 -# period_sink_count 2 # } # } # diff --git a/tools/topology/topology2/include/pipelines/cavs/dai-copier-be.conf b/tools/topology/topology2/include/pipelines/cavs/dai-copier-be.conf index b7bad256435b..46d0e689c165 100644 --- a/tools/topology/topology2/include/pipelines/cavs/dai-copier-be.conf +++ b/tools/topology/topology2/include/pipelines/cavs/dai-copier-be.conf @@ -37,7 +37,6 @@ Class.Pipeline."dai-copier-be" { Object.Widget { copier."1" { type dai_in - num_audio_formats 3 num_input_audio_formats 3 num_output_audio_formats 3 # 32-bit 48KHz 2ch @@ -70,7 +69,6 @@ Class.Pipeline."dai-copier-be" { } module-copier."2" { - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 Object.Base.audio_format.1 { diff --git a/tools/topology/topology2/include/pipelines/cavs/dai-copier-eqiir-module-copier-capture.conf b/tools/topology/topology2/include/pipelines/cavs/dai-copier-eqiir-module-copier-capture.conf index 7ddd8a3186d5..9dfff186df4c 100644 --- a/tools/topology/topology2/include/pipelines/cavs/dai-copier-eqiir-module-copier-capture.conf +++ b/tools/topology/topology2/include/pipelines/cavs/dai-copier-eqiir-module-copier-capture.conf @@ -48,9 +48,6 @@ Class.Pipeline."dai-copier-eqiir-module-copier-capture" { Object.Widget { copier."1" { type dai_out - period_sink_count 2 - period_source_count 0 - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 # copier only supports one format based on mixin/mixout requirements: 32-bit 48KHz 2ch @@ -63,7 +60,6 @@ Class.Pipeline."dai-copier-eqiir-module-copier-capture" { } eqiir."1" { - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 @@ -84,7 +80,6 @@ Class.Pipeline."dai-copier-eqiir-module-copier-capture" { } module-copier."2" { - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 Object.Base.audio_format.1 { diff --git a/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-mixin-capture.conf b/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-mixin-capture.conf index 56bf30581c6f..965adc174e74 100644 --- a/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-mixin-capture.conf +++ b/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-mixin-capture.conf @@ -47,10 +47,7 @@ Class.Pipeline."dai-copier-gain-mixin-capture" { Object.Widget { copier."1" { type dai_out - period_sink_count 2 - period_source_count 0 node_type $HDA_LINK_INPUT_CLASS - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 # copier only supports one format based on mixin/mixout requirements: 32-bit 48KHz 2ch @@ -64,7 +61,6 @@ Class.Pipeline."dai-copier-gain-mixin-capture" { mixin."1" {} gain."1" { - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 # 32-bit 48KHz 2ch diff --git a/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-module-copier-capture.conf b/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-module-copier-capture.conf index 4e5ca43e6702..dfa3c2752064 100644 --- a/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-module-copier-capture.conf +++ b/tools/topology/topology2/include/pipelines/cavs/dai-copier-gain-module-copier-capture.conf @@ -47,9 +47,6 @@ Class.Pipeline."dai-copier-gain-module-copier-capture" { Object.Widget { copier."1" { type dai_out - period_sink_count 2 - period_source_count 0 - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 # copier only supports one format based on mixin/mixout requirements: 32-bit 48KHz 2ch @@ -62,7 +59,6 @@ Class.Pipeline."dai-copier-gain-module-copier-capture" { } module-copier."2" { - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 Object.Base.audio_format.1 { @@ -73,7 +69,6 @@ Class.Pipeline."dai-copier-gain-module-copier-capture" { } } gain."1" { - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 diff --git a/tools/topology/topology2/include/pipelines/cavs/dai-kpb-be.conf b/tools/topology/topology2/include/pipelines/cavs/dai-kpb-be.conf index 03946ddbe996..65536755deea 100644 --- a/tools/topology/topology2/include/pipelines/cavs/dai-kpb-be.conf +++ b/tools/topology/topology2/include/pipelines/cavs/dai-kpb-be.conf @@ -44,7 +44,6 @@ Class.Pipeline."dai-kpb-be" { copier."1" { type dai_in node_type $HDA_LINK_OUTPUT_CLASS - num_audio_formats 3 num_input_audio_formats 3 num_output_audio_formats 3 # 32-bit 48KHz 2ch @@ -77,7 +76,6 @@ Class.Pipeline."dai-kpb-be" { } kpb."1" { - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 Object.Base.audio_format.1 { diff --git a/tools/topology/topology2/include/pipelines/cavs/deepbuffer-playback.conf b/tools/topology/topology2/include/pipelines/cavs/deepbuffer-playback.conf index 756966f284c5..fbb19283a9dd 100644 --- a/tools/topology/topology2/include/pipelines/cavs/deepbuffer-playback.conf +++ b/tools/topology/topology2/include/pipelines/cavs/deepbuffer-playback.conf @@ -17,7 +17,7 @@ # - + @@ -45,13 +45,12 @@ Class.Pipeline."deepbuffer-playback" { } Object.Widget { - copier."1" { - copier_type "host" + host-copier."1" { type "aif_in" node_type $HDA_HOST_OUTPUT_CLASS - num_audio_formats 3 num_input_audio_formats 3 num_output_audio_formats 3 + num_output_pins 1 deep_buffer_dma_ms $DEEPBUFFER_FW_DMA_MS # 16-bit 48KHz 2ch Object.Base.audio_format.1 { @@ -75,24 +74,18 @@ Class.Pipeline."deepbuffer-playback" { } gain."1" { - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 + num_input_audio_formats 1 + num_output_audio_formats 1 # 32-bit 48KHz 2ch - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.2 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } mixin."1" {} @@ -104,16 +97,12 @@ Class.Pipeline."deepbuffer-playback" { } } - Object.Base { - route.1 { - source copier.host.$index.1 - sink gain.$index.1 - } - route.2 { + Object.Base.route [ + { source gain.$index.1 sink mixin.$index.1 } - } + ] direction "playback" dynamic_pipeline 1 diff --git a/tools/topology/topology2/include/pipelines/cavs/gain-capture.conf b/tools/topology/topology2/include/pipelines/cavs/gain-capture.conf index 87466df972d4..57e65070b6db 100644 --- a/tools/topology/topology2/include/pipelines/cavs/gain-capture.conf +++ b/tools/topology/topology2/include/pipelines/cavs/gain-capture.conf @@ -18,7 +18,7 @@ # - + @@ -45,12 +45,11 @@ Class.Pipeline."gain-capture" { } Object.Widget { - copier."1" { - copier_type "host" + host-copier."1" { type "aif_out" - num_audio_formats 3 num_input_audio_formats 3 num_output_audio_formats 3 + num_input_pins 1 # 16-bit 48KHz 2ch Object.Base.audio_format.1 { in_bit_depth 32 @@ -74,7 +73,6 @@ Class.Pipeline."gain-capture" { } gain."1" { - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 @@ -90,7 +88,6 @@ Class.Pipeline."gain-capture" { } module-copier."2" { - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 #16-bit 48KHz 2ch @@ -110,13 +107,6 @@ Class.Pipeline."gain-capture" { } } - Object.Base { - route."1" { - source "gain.$index.1" - sink "copier.host.$index.1" - } - } - direction "capture" dynamic_pipeline 1 time_domain "timer" diff --git a/tools/topology/topology2/include/pipelines/cavs/gain-copier-capture.conf b/tools/topology/topology2/include/pipelines/cavs/gain-copier-capture.conf index 896717959a82..86ee039fd90e 100644 --- a/tools/topology/topology2/include/pipelines/cavs/gain-copier-capture.conf +++ b/tools/topology/topology2/include/pipelines/cavs/gain-copier-capture.conf @@ -18,7 +18,7 @@ # - + @@ -45,12 +45,11 @@ Class.Pipeline."gain-copier-capture" { } Object.Widget { - copier."1" { - copier_type "host" + host-copier."1" { type "aif_out" - num_audio_formats 3 num_input_audio_formats 3 num_output_audio_formats 3 + num_input_pins 1 # 16-bit 48KHz 2ch Object.Base.audio_format.1 { @@ -75,7 +74,6 @@ Class.Pipeline."gain-copier-capture" { } gain."1" { - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 #16-bit 48KHz 2ch @@ -90,7 +88,6 @@ Class.Pipeline."gain-copier-capture" { } module-copier."2" { - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 #16-bit 48KHz 2ch @@ -111,16 +108,12 @@ Class.Pipeline."gain-copier-capture" { } } - Object.Base { - route."1" { + Object.Base.route [ + { source "module-copier.$index.2" sink "gain.$index.1" } - route."2" { - source "gain.$index.1" - sink "copier.host.$index.1" - } - } + ] direction "capture" dynamic_pipeline 1 diff --git a/tools/topology/topology2/include/pipelines/cavs/gain-module-copier.conf b/tools/topology/topology2/include/pipelines/cavs/gain-module-copier.conf index e993745582fe..2989738bde61 100644 --- a/tools/topology/topology2/include/pipelines/cavs/gain-module-copier.conf +++ b/tools/topology/topology2/include/pipelines/cavs/gain-module-copier.conf @@ -46,7 +46,6 @@ Class.Pipeline."gain-module-copier" { Object.Widget { gain."1" { - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 @@ -61,7 +60,6 @@ Class.Pipeline."gain-module-copier" { } } module-copier."1" { - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 diff --git a/tools/topology/topology2/include/pipelines/cavs/gain-playback.conf b/tools/topology/topology2/include/pipelines/cavs/gain-playback.conf index 81453a916214..81aedde59f7f 100644 --- a/tools/topology/topology2/include/pipelines/cavs/gain-playback.conf +++ b/tools/topology/topology2/include/pipelines/cavs/gain-playback.conf @@ -17,7 +17,7 @@ # - + @@ -44,12 +44,11 @@ Class.Pipeline."gain-playback" { } Object.Widget { - copier."1" { - copier_type "host" + host-copier."1" { type "aif_in" - num_audio_formats 3 num_input_audio_formats 3 num_output_audio_formats 3 + num_output_pins 1 # 16-bit 48KHz 2ch Object.Base.audio_format.1 { out_bit_depth 32 @@ -73,7 +72,6 @@ Class.Pipeline."gain-playback" { } gain."1" { - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 #16-bit 48KHz 2ch @@ -93,13 +91,6 @@ Class.Pipeline."gain-playback" { } } - Object.Base { - route."1" { - source "copier.host.$index.1" - sink "gain.$index.1" - } - } - direction "playback" dynamic_pipeline 1 time_domain "timer" diff --git a/tools/topology/topology2/include/pipelines/cavs/google-rtc-aec-capture.conf b/tools/topology/topology2/include/pipelines/cavs/google-rtc-aec-capture.conf new file mode 100644 index 000000000000..58b7dfbffb04 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/google-rtc-aec-capture.conf @@ -0,0 +1,125 @@ +# +# cAVS google-rtc-aec capture pipeline +# +# A google-rtc-aec capture pipeline. All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.google-rtc-aec-capture.N.attribute_name" +# +# Usage: google-rtc-aec-capture pipeline object can be instantiated as: +# +# Object.Pipeline.google-rtc-aec-capture."N" { +# format "s16le" +# period 1000 +# time_domain "timer" +# channels 2 +# rate 48000 +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + + + + + + + +Class.Pipeline."google-rtc-aec-capture" { + + DefineAttribute."index" {} + + + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # google-rtc-aec-capture objects instantiated within the same alsaconf node must have + # unique pipeline_id attribute + # + unique "instance" + } + + Object.Widget { + pipeline."1" { + priority 0 + lp_mode 0 + } + + module-copier."1" { + period_sink_count 1 + period_source_count 1 + num_audio_formats 1 + num_input_audio_formats 1 + num_output_audio_formats 1 + + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 16 + out_valid_bit_depth 16 + } + } + + google-rtc-aec."1" { + Object.Control.bytes."1" { + name google-rtc-aec_blob + access [ + tlv_read + tlv_callback + ] + + Object.Base.extops."extctl" { + get 258 + put 0 + } + max 4096 + + IncludeByKey.GOOGLE_RTC_AEC_SUPPORT { + "[1]" "include/components/google-rtc-aec/rtc-aec-blob.conf" + } + } + } + + module-copier."2" { + period_sink_count 1 + period_source_count 1 + num_audio_formats 1 + num_input_audio_formats 1 + num_output_audio_formats 1 + + Object.Base.audio_format.1 { + in_bit_depth 16 + in_valid_bit_depth 16 + out_bit_depth 32 + out_valid_bit_depth 32 + } + } + } + + Object.Base { + route.1 { + source module-copier.$index.1 + sink google-rtc-aec.$index.1 + } + route.2 { + source google-rtc-aec.$index.1 + sink module-copier.$index.2 + } + } + + direction "capture" + dynamic_pipeline 1 + time_domain "timer" + channels 2 + channels_min 2 + channels_max 2 + rate 48000 + rate_min 16000 + rate_max 48000 +} diff --git a/tools/topology/topology2/include/pipelines/cavs/highpass-capture-be.conf b/tools/topology/topology2/include/pipelines/cavs/highpass-capture-be.conf index 9ad3dc93357c..b18666ef7ffc 100644 --- a/tools/topology/topology2/include/pipelines/cavs/highpass-capture-be.conf +++ b/tools/topology/topology2/include/pipelines/cavs/highpass-capture-be.conf @@ -40,7 +40,6 @@ Class.Pipeline."highpass-capture-be" { Object.Widget { copier."1" { type dai_in - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 @@ -53,7 +52,6 @@ Class.Pipeline."highpass-capture-be" { } eqiir."1" { - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 diff --git a/tools/topology/topology2/include/pipelines/cavs/host-copier-gain-mixin-playback.conf b/tools/topology/topology2/include/pipelines/cavs/host-copier-gain-mixin-playback.conf index cc803132a7d5..814e78252eb8 100644 --- a/tools/topology/topology2/include/pipelines/cavs/host-copier-gain-mixin-playback.conf +++ b/tools/topology/topology2/include/pipelines/cavs/host-copier-gain-mixin-playback.conf @@ -17,7 +17,7 @@ # - + @@ -45,13 +45,12 @@ Class.Pipeline."host-copier-gain-mixin-playback" { } Object.Widget { - copier."1" { - copier_type "host" + host-copier."1" { type "aif_in" node_type $HDA_HOST_OUTPUT_CLASS - num_audio_formats 3 num_input_audio_formats 3 num_output_audio_formats 3 + num_output_pins 1 # 16-bit 48KHz 2ch Object.Base.audio_format.1 { out_bit_depth 32 @@ -74,24 +73,18 @@ Class.Pipeline."host-copier-gain-mixin-playback" { } gain."1" { - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 + num_input_audio_formats 1 + num_output_audio_formats 1 # 32-bit 48KHz 2ch - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.2 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } mixin."1" {} @@ -102,16 +95,12 @@ Class.Pipeline."host-copier-gain-mixin-playback" { } } - Object.Base { - route.1 { - source copier.host.$index.1 - sink gain.$index.1 - } - route.2 { + Object.Base.route [ + { source gain.$index.1 sink mixin.$index.1 } - } + ] direction "playback" dynamic_pipeline 1 diff --git a/tools/topology/topology2/include/pipelines/cavs/host-copier-gain-src-mixin-playback.conf b/tools/topology/topology2/include/pipelines/cavs/host-copier-gain-src-mixin-playback.conf index 6139b5574bee..c8b3d5f4216a 100644 --- a/tools/topology/topology2/include/pipelines/cavs/host-copier-gain-src-mixin-playback.conf +++ b/tools/topology/topology2/include/pipelines/cavs/host-copier-gain-src-mixin-playback.conf @@ -16,8 +16,9 @@ # Where N is the unique pipeline ID within the same alsaconf node. # - - + + + @@ -46,10 +47,10 @@ Class.Pipeline."host-copier-gain-src-mixin-playback" { } Object.Widget { - copier."1" { - copier_type "host" + host-copier."1" { type "aif_in" node_type $HDA_HOST_OUTPUT_CLASS + num_output_pins 1 } @@ -72,20 +73,16 @@ Class.Pipeline."host-copier-gain-src-mixin-playback" { } } - Object.Base { - route.1 { - source copier.host..1 - sink gain..1 + Object.Base.route [ + { + source gain.$index.1 + sink src.$index.1 } - route.2 { - source gain..1 - sink src..1 + { + source src.$index.1 + sink mixin.$index.1 } - route.3 { - source src..1 - sink mixin..1 - } - } + ] direction "playback" dynamic_pipeline 1 diff --git a/tools/topology/topology2/include/pipelines/cavs/host-gateway-capture.conf b/tools/topology/topology2/include/pipelines/cavs/host-gateway-capture.conf index a0e2c437ae62..deb9df7f9650 100644 --- a/tools/topology/topology2/include/pipelines/cavs/host-gateway-capture.conf +++ b/tools/topology/topology2/include/pipelines/cavs/host-gateway-capture.conf @@ -17,7 +17,7 @@ # - + Class.Pipeline."host-gateway-capture" { @@ -43,11 +43,10 @@ Class.Pipeline."host-gateway-capture" { } Object.Widget { - copier."1" { - copier_type "host" + host-copier."1" { type "aif_out" node_type $HDA_HOST_INPUT_CLASS - num_audio_formats 6 + num_input_pins 1 num_input_audio_formats 6 num_output_audio_formats 6 # 16-bit output format 48KHz 2ch. Input sample format is always 32-bit for capture diff --git a/tools/topology/topology2/include/pipelines/cavs/host-gateway-playback.conf b/tools/topology/topology2/include/pipelines/cavs/host-gateway-playback.conf index 6e0312391490..577513ad77b4 100644 --- a/tools/topology/topology2/include/pipelines/cavs/host-gateway-playback.conf +++ b/tools/topology/topology2/include/pipelines/cavs/host-gateway-playback.conf @@ -16,7 +16,7 @@ # Where N is the unique pipeline ID within the same alsaconf node. # - + @@ -43,11 +43,10 @@ Class.Pipeline."host-gateway-playback" { } Object.Widget { - copier."1" { - copier_type "host" + host-copier."1" { node_type $HDA_HOST_OUTPUT_CLASS type "aif_in" - num_audio_formats 3 + num_output_pins 1 num_input_audio_formats 3 num_output_audio_formats 3 # 16-bit input format 48KHz 2ch. Output sample format is always 32-bit for playback diff --git a/tools/topology/topology2/include/pipelines/cavs/io-gateway-capture.conf b/tools/topology/topology2/include/pipelines/cavs/io-gateway-capture.conf index dc53e003dee1..0675ccd98ed5 100644 --- a/tools/topology/topology2/include/pipelines/cavs/io-gateway-capture.conf +++ b/tools/topology/topology2/include/pipelines/cavs/io-gateway-capture.conf @@ -38,7 +38,6 @@ Class.Pipeline."io-gateway-capture" { Object.Widget { copier."1" { type dai_in - num_audio_formats 1 num_input_audio_formats 1 num_output_audio_formats 1 @@ -57,6 +56,7 @@ Class.Pipeline."io-gateway-capture" { } time_domain "timer" + direction "capture" dynamic_pipeline 1 channels 2 channels_min 2 diff --git a/tools/topology/topology2/include/pipelines/cavs/io-gateway.conf b/tools/topology/topology2/include/pipelines/cavs/io-gateway.conf index 8b1ecffec2c4..065ecc71012c 100644 --- a/tools/topology/topology2/include/pipelines/cavs/io-gateway.conf +++ b/tools/topology/topology2/include/pipelines/cavs/io-gateway.conf @@ -42,36 +42,36 @@ Class.Pipeline."io-gateway" { Object.Widget { copier."1" { type dai_in - num_audio_formats 3 num_input_audio_formats 3 num_output_audio_formats 3 # 32-bit 48KHz 2ch - Object.Base.audio_format.3 { - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - # 32-bit 48KHz 4ch - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 - } + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 24 + out_bit_depth 32 + out_valid_bit_depth 24 + } + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + # 32-bit 48KHz 4ch + { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] } pipeline."1" { diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-alh-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-alh-dai-copier-playback.conf new file mode 100644 index 000000000000..a66f846f7d04 --- /dev/null +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-alh-dai-copier-playback.conf @@ -0,0 +1,109 @@ +# +# BE playback pipeline: mixout-gain-alh-dai-copier. +# +# All attributes defined herein are namespaced +# by alsatplg to "Object.Pipeline.mixout-gain-alh-dai-copier-playback.N.attribute_name" +# +# Usage: mixout-gain-alh-dai-copier-playback pipeline object can be instantiated as: +# +# Object.Pipeline.mixout-gain-alh-dai-copier-playback."N" { +# time_domain "timer" +# rate 48000 +# } +# +# Where N is the unique pipeline ID within the same alsaconf node. +# + + + + + + + +Class.Pipeline."mixout-gain-alh-dai-copier-playback" { + + DefineAttribute."index" {} + + + + attributes { + !constructor [ + "index" + ] + + !immutable [ + "direction" + ] + + # + # mixout-gain-alh-dai-copier-playback objects instantiated within the same alsaconf + # node must have unique instance attribute + # + unique "instance" + } + + Object.Widget { + mixout."1" {} + alh-copier."1" { + type dai_in + num_input_audio_formats 1 + num_output_audio_formats 1 + num_input_pins 1 + + # copier only supports one format based on mixin/mixout requirements: + # 32-bit 48KHz 2ch + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + gain."1" { + num_input_audio_formats 1 + num_output_audio_formats 1 + + # 32-bit 48KHz 2ch + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + + pipeline."1" { + priority 0 + lp_mode 0 + } + } + + Object.Base { + route.1 { + source mixout.$index.1 + sink gain.$index.1 + } + } + + direction "playback" + dynamic_pipeline 1 + time_domain "timer" + channels 2 + channels_min 2 + channels_max 2 + rate 48000 + rate_min 48000 + rate_max 48000 +} diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dai-copier-playback.conf index 6ff3115fffe8..94316c85209e 100644 --- a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dai-copier-playback.conf +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-dai-copier-playback.conf @@ -48,46 +48,32 @@ Class.Pipeline."mixout-gain-dai-copier-playback" { mixout."1" {} copier."1" { type dai_in - period_sink_count 0 - period_source_count 2 - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 + num_input_audio_formats 1 + num_output_audio_formats 1 # copier only supports one format based on mixin/mixout requirements: 32-bit 48KHz 2ch - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.2 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } gain."1" { - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 + num_input_audio_formats 1 + num_output_audio_formats 1 # 32-bit 48KHz 2ch - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.2 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } pipeline."1" { diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-efx-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-efx-dai-copier-playback.conf index 677420b800c4..428c9969e3a4 100644 --- a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-efx-dai-copier-playback.conf +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-efx-dai-copier-playback.conf @@ -52,9 +52,6 @@ Class.Pipeline."mixout-gain-efx-dai-copier-playback" { mixout."1" {} copier."1" { type dai_in - period_sink_count 0 - period_source_count 2 - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 @@ -74,7 +71,6 @@ Class.Pipeline."mixout-gain-efx-dai-copier-playback" { } } gain."1" { - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 @@ -94,7 +90,6 @@ Class.Pipeline."mixout-gain-efx-dai-copier-playback" { } } eqiir."1" { - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 @@ -120,7 +115,6 @@ Class.Pipeline."mixout-gain-efx-dai-copier-playback" { } } eqfir."1" { - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-host-copier-capture.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-host-copier-capture.conf index 1a7afeaf0fa2..594251d66062 100644 --- a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-host-copier-capture.conf +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-host-copier-capture.conf @@ -17,7 +17,7 @@ # - + @@ -47,13 +47,12 @@ Class.Pipeline."mixout-gain-host-copier-capture" { Object.Widget { mixout."1" {} - copier."1" { - copier_type "host" + host-copier."1" { type "aif_out" node_type $HDA_HOST_INPUT_CLASS - num_audio_formats 4 num_input_audio_formats 4 num_output_audio_formats 4 + num_input_pins 1 # 16-bit 48KHz 2ch Object.Base.audio_format.1 { in_bit_depth 32 @@ -84,7 +83,6 @@ Class.Pipeline."mixout-gain-host-copier-capture" { } gain."1"{ - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 @@ -110,16 +108,12 @@ Class.Pipeline."mixout-gain-host-copier-capture" { } } - Object.Base { - route.1 { - source mixout.$index.1 - sink gain.$index.1 - } - route.2 { + Object.Base.route [ + { source gain.$index.1 sink copier.host.$index.1 } - } + ] direction "capture" dynamic_pipeline 1 diff --git a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-smart-amp-dai-copier-playback.conf b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-smart-amp-dai-copier-playback.conf index cc24fcaf04f2..e9490c0e62bb 100644 --- a/tools/topology/topology2/include/pipelines/cavs/mixout-gain-smart-amp-dai-copier-playback.conf +++ b/tools/topology/topology2/include/pipelines/cavs/mixout-gain-smart-amp-dai-copier-playback.conf @@ -47,44 +47,32 @@ Class.Pipeline."mixout-gain-smart-amp-dai-copier-playback" { mixout."1" {} copier."1" { type dai_in - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 + num_input_audio_formats 1 + num_output_audio_formats 1 # copier only supports one format based on mixin/mixout requirements: 32-bit 48KHz 2ch - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.2 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } gain."1" { - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 + num_input_audio_formats 1 + num_output_audio_formats 1 # 32-bit 48KHz 2ch - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 24 - out_bit_depth 32 - out_valid_bit_depth 24 - } - - Object.Base.audio_format.2 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } smart_amp."1" { @@ -93,18 +81,18 @@ Class.Pipeline."mixout-gain-smart-amp-dai-copier-playback" { # 32-bit 48KHz 2ch Object.Base.input_audio_format { 1 { - pin_index 0 + input_pin_index 0 in_bit_depth 32 in_valid_bit_depth 32 } 2 { - pin_index 1 + input_pin_index 1 in_bit_depth 32 in_valid_bit_depth 32 } } Object.Base.output_audio_format.1 { - pin_index 0 + output_pin_index 0 out_bit_depth 32 out_valid_bit_depth 32 } diff --git a/tools/topology/topology2/include/pipelines/cavs/src-gain-mixin-playback.conf b/tools/topology/topology2/include/pipelines/cavs/src-gain-mixin-playback.conf index a8e733b1625d..aaab347faf37 100644 --- a/tools/topology/topology2/include/pipelines/cavs/src-gain-mixin-playback.conf +++ b/tools/topology/topology2/include/pipelines/cavs/src-gain-mixin-playback.conf @@ -15,8 +15,10 @@ # # Where N is the unique pipeline ID within the same alsaconf node. # + + - + @@ -41,9 +43,9 @@ Class.Pipeline."src-gain-mixin-playback" { } Object.Widget { - copier."1" { - copier_type "host" + host-copier."1" { type "aif_in" + num_output_pins 1 @@ -57,7 +59,6 @@ Class.Pipeline."src-gain-mixin-playback" { } gain."1" { - num_audio_formats 3 num_input_audio_formats 3 num_output_audio_formats 3 #16-bit 48KHz 2ch @@ -86,22 +87,16 @@ Class.Pipeline."src-gain-mixin-playback" { } } - Object.Base { - route."1" { - source "copier.host.$index.1" - sink "src.$index.1" - } - - route."2" { + Object.Base.route [ + { source "src.$index.1" sink "gain.$index.1" } - - route."3" { + { source "gain.$index.1" sink "mixin.$index.1" - } - } + } + ] direction "playback" dynamic_pipeline 1 diff --git a/tools/topology/topology2/platform/intel/bt-generic.conf b/tools/topology/topology2/platform/intel/bt-generic.conf index caf29289dec7..fdd4fa399844 100644 --- a/tools/topology/topology2/platform/intel/bt-generic.conf +++ b/tools/topology/topology2/platform/intel/bt-generic.conf @@ -22,7 +22,6 @@ Object.Pipeline { copier_type "SSP" stream_name $BT_NAME node_type $I2S_LINK_OUTPUT_CLASS - num_audio_formats 3 num_input_audio_formats 3 num_output_audio_formats 3 Object.Base.audio_format.0 { @@ -63,9 +62,9 @@ Object.Pipeline { Object.Widget.pipeline.1 { stream_name $BT_PB_PIPELINE_STREAM_NAME } - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $BT_PB_PCM_CAPS - num_audio_formats 3 + pcm_id $BT_PCM_ID num_input_audio_formats 3 num_output_audio_formats 3 Object.Base.audio_format.0 { @@ -107,9 +106,9 @@ Object.Pipeline { Object.Widget.pipeline.1 { stream_name $BT_CP_PIPELINE_STREAM_NAME } - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $BT_CP_PCM_CAPS - num_audio_formats 3 + pcm_id $BT_PCM_ID num_input_audio_formats 3 num_output_audio_formats 3 Object.Base.audio_format.0 { @@ -159,7 +158,6 @@ Object.Pipeline { copier_type "SSP" stream_name $BT_NAME node_type $I2S_LINK_INPUT_CLASS - num_audio_formats 4 num_input_audio_formats 4 num_output_audio_formats 4 Object.Base.audio_format.0 { @@ -197,12 +195,12 @@ Object.Pipeline { Object.Base.route [ { - source $BT_PB_DAI_PIPELINE_SRC + source "host-copier.$BT_PCM_ID.playback" sink $BT_PB_HOST_PIPELINE_SINK } { source $BT_CP_DAI_PIPELINE_SRC - sink $BT_CP_HOST_PIPELINE_SINK + sink "host-copier.$BT_PCM_ID.capture" } ] diff --git a/tools/topology/topology2/platform/intel/bt-ssp-config-lbm.conf b/tools/topology/topology2/platform/intel/bt-ssp-config-lbm.conf index afbc6c2ba267..694f6939e2f6 100644 --- a/tools/topology/topology2/platform/intel/bt-ssp-config-lbm.conf +++ b/tools/topology/topology2/platform/intel/bt-ssp-config-lbm.conf @@ -48,7 +48,7 @@ Object.Dai.SSP [ id 2 name "BT-A2DP" mclk_freq $BT_MCLK - bclk_freq 3072000 + bclk_freq 1536000 tdm_slot_width 16 format "DSP_A" bclk "codec_consumer" diff --git a/tools/topology/topology2/platform/intel/common_definitions.conf b/tools/topology/topology2/platform/intel/common_definitions.conf index f4d49718f559..9c684c7968c0 100644 --- a/tools/topology/topology2/platform/intel/common_definitions.conf +++ b/tools/topology/topology2/platform/intel/common_definitions.conf @@ -58,6 +58,7 @@ Define { SPI_INPUT_CLASS 26 # SPI Input (DSP <-) DEEPBUFFER_FW_DMA_MS 100 # 100 ms copier dma size + DEEPBUFFER_D0I3_COMPATIBLE false # Deep buffer PCM is not D0I3 compatible SSP_BLOB_VERSION_1_0 0x100 SSP_BLOB_VERSION_1_5 0x105 diff --git a/tools/topology/topology2/platform/intel/deep-buffer.conf b/tools/topology/topology2/platform/intel/deep-buffer.conf index 7bf828638906..047e409a26e2 100644 --- a/tools/topology/topology2/platform/intel/deep-buffer.conf +++ b/tools/topology/topology2/platform/intel/deep-buffer.conf @@ -2,8 +2,9 @@ Object.Pipeline.deepbuffer-playback [ { index $DEEP_BUFFER_PIPELINE_ID - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $DEEP_BUFFER_PCM_NAME + pcm_id $DEEP_BUFFER_PCM_ID } Object.Widget.gain.1 { @@ -19,7 +20,7 @@ Object.PCM.pcm [ name $DEEP_BUFFER_PCM_NAME id $DEEP_BUFFER_PCM_ID direction playback - playback_compatible_d0i3 true + playback_compatible_d0i3 $DEEPBUFFER_D0I3_COMPATIBLE Object.Base.fe_dai.1 { name "DeepBuffer" @@ -37,4 +38,8 @@ Object.Base.route [ source $DEEP_BUFFER_PIPELINE_SRC sink $DEEP_BUFFER_PIPELINE_SINK } + { + source host-copier.$DEEP_BUFFER_PCM_ID.playback + sink gain.$DEEP_BUFFER_PIPELINE_ID.1 + } ] diff --git a/tools/topology/topology2/platform/intel/dmic-default.conf b/tools/topology/topology2/platform/intel/dmic-default.conf index d5bfb7d11f1e..65f75e4199e8 100644 --- a/tools/topology/topology2/platform/intel/dmic-default.conf +++ b/tools/topology/topology2/platform/intel/dmic-default.conf @@ -33,5 +33,6 @@ Define { WOV_UUID '1f:d5:a8:eb:27:78:b5:47:82:ee:de:6e:77:43:af:67' WOV_CPC '360000' DMIC1_PCM_CAPS 'Passthrough Capture 18' - + DMIC_CORE_ID 0 + PASSTHROUGH "false" } diff --git a/tools/topology/topology2/platform/intel/dmic-generic.conf b/tools/topology/topology2/platform/intel/dmic-generic.conf index 4c0261be3745..8c1fc2654f01 100644 --- a/tools/topology/topology2/platform/intel/dmic-generic.conf +++ b/tools/topology/topology2/platform/intel/dmic-generic.conf @@ -62,186 +62,286 @@ Object.Dai.DMIC [ } ] -IncludeByKey.INCLUDE_WOV { - "true" "platform/intel/dmic-wov.conf" -} +IncludeByKey.PASSTHROUGH { +"false" { + IncludeByKey.INCLUDE_WOV { + "true" "platform/intel/dmic-wov.conf" + } -Object.Pipeline.gain-capture [ - { - format $FORMAT - index $DMIC0_HOST_PIPELINE_ID + Object.Pipeline.gain-capture [ + { + format $FORMAT + index $DMIC0_HOST_PIPELINE_ID - Object.Widget.copier.1 { - stream_name $DMIC0_PCM_CAPS - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 - } - } - Object.Widget.gain.1 { - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 - } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 - } - Object.Control.mixer.1 { - name 'DMIC0 Capture Volume 1' - } - } + Object.Widget.host-copier.1 { + stream_name $DMIC0_PCM_CAPS + core_id $DMIC_CORE_ID + pcm_id $DMIC0_PCM_ID + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + Object.Widget.gain.1 { + core_id $DMIC_CORE_ID + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + Object.Control.mixer.1 { + name 'DMIC0 Capture Volume 1' + } + } - Object.Widget.module-copier."2" { - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 + Object.Widget.module-copier."2" { + core_id $DMIC_CORE_ID + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + Object.Widget.pipeline."1" { + core $DMIC_CORE_ID + } } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 - } - } - } -] + ] -Object.Pipeline.dai-copier-eqiir-module-copier-capture [ - { - index $DMIC0_DAI_PIPELINE_ID + Object.Pipeline.dai-copier-eqiir-module-copier-capture [ + { + index $DMIC0_DAI_PIPELINE_ID + + Object.Widget.copier.1 { + core_id $DMIC_CORE_ID + dai_index 0 + dai_type "DMIC" + copier_type "DMIC" + type dai_out + stream_name $DMIC0_NAME + node_type $DMIC_LINK_INPUT_CLASS + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } - Object.Widget.copier.1 { - dai_index 0 - dai_type "DMIC" - copier_type "DMIC" - type dai_out - stream_name $DMIC0_NAME - node_type $DMIC_LINK_INPUT_CLASS - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 + Object.Widget.module-copier."2" { + core_id $DMIC_CORE_ID + stream_name $DMIC0_NAME + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + } + + Object.Widget.eqiir.1 { + core_id $DMIC_CORE_ID + num_input_audio_formats 2 + num_output_audio_formats 2 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Base.audio_format.2 { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + } + Object.Control.bytes."1" { + name 'DMIC0 capture Iir Eq' + } + } + Object.Widget.pipeline."1" { + core $DMIC_CORE_ID + } } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 + ] + Object.Base.route [ + { + source $DMIC0_DAI_COPIER + sink $DMIC0_DAI_GAIN } - } - - Object.Widget.module-copier."2" { - stream_name $DMIC0_NAME - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 + { + source $DMIC0_DAI_PIPELINE_SRC + sink $DMIC0_HOST_PIPELINE_SINK } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 - in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - in_ch_map $CHANNEL_MAP_3_POINT_1 - out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 - out_ch_map $CHANNEL_MAP_3_POINT_1 + { + source "gain.$DMIC0_HOST_PIPELINE_ID.1" + sink "host-copier.$DMIC0_PCM_ID.capture" } - } - - Object.Widget.eqiir.1 { - num_audio_formats 2 - num_input_audio_formats 2 - num_output_audio_formats 2 - Object.Base.audio_format.1 { - in_bit_depth 32 - in_valid_bit_depth 32 - out_bit_depth 32 - out_valid_bit_depth 32 + ] + } +"true" { + Object.Pipeline.host-gateway-capture [ + { + index $DMIC0_HOST_PIPELINE_ID + Object.Widget.host-copier.1 { + stream_name $DMIC0_PCM_CAPS + pcm_id $DMIC0_PCM_ID + num_input_audio_formats 2 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + num_output_audio_formats 2 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } } - Object.Base.audio_format.2 { - in_channels 4 - in_bit_depth 32 - in_valid_bit_depth 32 - out_channels 4 - out_bit_depth 32 - out_valid_bit_depth 32 + ] + Object.Pipeline.io-gateway-capture [ + { + index $DMIC0_DAI_PIPELINE_ID + Object.Widget.copier.1 { + dai_index 0 + dai_type "DMIC" + copier_type "DMIC" + type dai_out + stream_name $DMIC0_NAME + node_type $DMIC_LINK_INPUT_CLASS + num_input_audio_formats 2 + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + num_output_audio_formats 2 + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + { + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } } - Object.Control.bytes."1" { - name 'DMIC0 capture Iir Eq' + ] + Object.Base.route [ + { + source "copier.DMIC.$DMIC0_DAI_PIPELINE_ID.1" + sink "host-copier.$DMIC0_PCM_ID.capture" } - } + ] } -] - -Object.Base.route [ - { - source $DMIC0_DAI_PIPELINE_SRC - sink $DMIC0_HOST_PIPELINE_SINK - } - { - source $DMIC0_DAI_COPIER - sink $DMIC0_DAI_GAIN - } -] +} Object.PCM.pcm [ { diff --git a/tools/topology/topology2/platform/intel/dmic-wov.conf b/tools/topology/topology2/platform/intel/dmic-wov.conf index f6e43be05972..37796b178077 100644 --- a/tools/topology/topology2/platform/intel/dmic-wov.conf +++ b/tools/topology/topology2/platform/intel/dmic-wov.conf @@ -7,8 +7,9 @@ Object.Pipeline { rate_max 16000 index $DMIC1_HOST_PIPELINE_ID - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $DMIC1_PCM_CAPS + pcm_id 11 Object.Base.audio_format.1 { in_rate 16000 in_bit_depth 32 @@ -52,7 +53,6 @@ Object.Pipeline { type dai_out stream_name $DMIC1_NAME node_type $DMIC_LINK_INPUT_CLASS - num_audio_formats 2 num_input_audio_formats 2 num_output_audio_formats 2 Object.Base.audio_format.1 { @@ -109,7 +109,7 @@ Object.Pipeline { Object.Base.route [ { source $DMIC_WOV_DAI_PIPELINE_KPB - sink $DMIC1_HOST_PIPELINE_SINK + sink "host-copier.11.capture" } { source $DMIC_WOV_DAI_PIPELINE_KPB @@ -117,7 +117,7 @@ Object.Base.route [ } { source $WOV_PIPELINE_VIRTUAL - sink $DMIC1_HOST_PIPELINE_SINK + sink "host-copier.11.capture" } ] diff --git a/tools/topology/topology2/platform/intel/google-rtc-aec-reference.conf b/tools/topology/topology2/platform/intel/google-rtc-aec-reference.conf new file mode 100644 index 000000000000..430d16373bf9 --- /dev/null +++ b/tools/topology/topology2/platform/intel/google-rtc-aec-reference.conf @@ -0,0 +1,104 @@ +Object.Pipeline.google-rtc-aec-capture [ + { + index 18 + Object.Widget.pipeline.1 { + stream_name "DMIC0 RTC AEC" + } + + Object.Widget.google-rtc-aec.1 { + Object.Base.input_pin_binding.1 { + input_pin_binding_name "module-copier.18.1" + } + + Object.Base.input_pin_binding.2 { + input_pin_binding_name $GOOGLE_RTC_AEC_REF_SOURCE + } + } + } +] + +Object.Pipeline.host-gateway-capture[ + { + index 19 + + Object.Widget.host-copier.1 { + stream_name "DMIC0 AEC" + pcm_id 27 + } + } +] + +Object.Pipeline.gain-capture [ + { + index 20 + + Object.Widget.host-copier.1 { + stream_name "DMIC0 AN" + pcm_id 28 + } + + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name 'AN Volume' + } + } + } +] + +Object.PCM.pcm [ + { + name "DMIC0 RTC AEC" + id 27 + direction "capture" + Object.Base.fe_dai.1 { + name "DMIC0 RTC AEC" + } + + Object.PCM.pcm_caps.1 { + name "DMIC0 AEC" + # only 32-bit capture supported now + formats 'S32_LE' + channels_min $NUM_DMICS + channels_max $NUM_DMICS + } + } + { + name "DMIC0 RTC AEC NS" + id 28 + direction "capture" + Object.Base.fe_dai.1 { + name "DMIC0 RTC AEC NS" + } + + Object.PCM.pcm_caps.1 { + name "DMIC0 AN" + # only 32-bit capture supported now + formats 'S32_LE' + channels_min $NUM_DMICS + channels_max $NUM_DMICS + } + } +] + +Object.Base.route [ + { + source $DMIC0_DAI_PIPELINE_SRC + sink module-copier.18.1 + } + { + source $GOOGLE_RTC_AEC_REF_SOURCE + sink "google-rtc-aec.18.1" + } + { + source "module-copier.18.2" + sink "host-copier.27.capture" + } + { + source "module-copier.18.2" + sink "gain.20.1" + } + { + source "gain.20.1" + sink "host-copier.28.capture" + } +] diff --git a/tools/topology/topology2/platform/intel/hdmi-generic.conf b/tools/topology/topology2/platform/intel/hdmi-generic.conf index 3cbf2d48b727..4a8792751da8 100644 --- a/tools/topology/topology2/platform/intel/hdmi-generic.conf +++ b/tools/topology/topology2/platform/intel/hdmi-generic.conf @@ -34,24 +34,27 @@ Object.Dai.HDA [ Object.Pipeline { host-gateway-playback [ { - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $HDMI1_PCM_CAPS + pcm_id $HDMI1_PCM_ID } index $HDMI1_HOST_PIPELINE_ID use_chain_dma $USE_CHAIN_DMA } { - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $HDMI2_PCM_CAPS + pcm_id $HDMI2_PCM_ID } index $HDMI2_HOST_PIPELINE_ID use_chain_dma $USE_CHAIN_DMA } { - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $HDMI3_PCM_CAPS + pcm_id $HDMI3_PCM_ID } index $HDMI3_HOST_PIPELINE_ID @@ -68,6 +71,18 @@ Object.Pipeline { stream_name "iDisp1" dai_type "HDA" copier_type "HDA" + num_input_audio_formats 1 + num_output_audio_formats 1 + + # copier only supports 32-bit 48KHz 2ch + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } use_chain_dma $USE_CHAIN_DMA } @@ -80,6 +95,18 @@ Object.Pipeline { stream_name 'iDisp2' dai_type "HDA" copier_type "HDA" + num_input_audio_formats 1 + num_output_audio_formats 1 + + # copier only supports 32-bit 48KHz 2ch + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } use_chain_dma $USE_CHAIN_DMA } @@ -91,6 +118,18 @@ Object.Pipeline { stream_name 'iDisp3' dai_type "HDA" copier_type "HDA" + num_input_audio_formats 1 + num_output_audio_formats 1 + + # copier only supports 32-bit 48KHz 2ch + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } use_chain_dma $USE_CHAIN_DMA } @@ -142,15 +181,15 @@ Object.PCM.pcm [ # top-level pipeline connections Object.Base.route [ { - source $HDMI1_HOST_PIPELINE_SINK + source "host-copier.$HDMI1_PCM_ID.playback" sink $HDMI1_DAI_PIPELINE_SRC } { - source $HDMI2_HOST_PIPELINE_SINK + source "host-copier.$HDMI2_PCM_ID.playback" sink $HDMI2_DAI_PIPELINE_SRC } { - source $HDMI3_HOST_PIPELINE_SINK + source "host-copier.$HDMI3_PCM_ID.playback" sink $HDMI3_DAI_PIPELINE_SRC } ] @@ -180,14 +219,27 @@ IncludeByKey.NUM_HDMIS { stream_name 'iDisp4' dai_type "HDA" copier_type "HDA" + num_input_audio_formats 1 + num_output_audio_formats 1 + + # copier only supports 32-bit 48KHz 2ch + Object.Base.audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } use_chain_dma $USE_CHAIN_DMA } ] Object.Pipeline.host-gateway-playback [ { - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $HDMI4_PCM_CAPS + pcm_id $HDMI4_PCM_ID } index $HDMI4_HOST_PIPELINE_ID @@ -211,7 +263,7 @@ IncludeByKey.NUM_HDMIS { ] Object.Base.route [ { - source $HDMI4_HOST_PIPELINE_SINK + source "host-copier.$HDMI4_PCM_ID.playback" sink $HDMI4_DAI_PIPELINE_SRC } ] diff --git a/tools/topology/topology2/platform/intel/nocodec-ssp0-2level.conf b/tools/topology/topology2/platform/intel/nocodec-ssp0-2level.conf index a2d907ea22c9..8eb119911bd5 100644 --- a/tools/topology/topology2/platform/intel/nocodec-ssp0-2level.conf +++ b/tools/topology/topology2/platform/intel/nocodec-ssp0-2level.conf @@ -5,8 +5,9 @@ Object.Pipeline.host-copier-gain-mixin-playback [ Object.Widget.pipeline.1 { stream_name 'NoCodec-0' } - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name 'SSP0 Aux Playback' + pcm_id $SSP0_MIXER_PCM_ID_1 } Object.Widget.gain.1 { Object.Control.mixer.1 { @@ -49,6 +50,11 @@ Object.Base.route [ source $SSP0_MIXER_SOURCE_2 sink $SSP0_MIXER_SINK_1 } + { + source host-copier.$SSP0_MIXER_PCM_ID_1.playback + sink gain.$SSP0_MIXER_PIPELINE_ID_2.1 + } + { source $SSP0_MIXER_SOURCE_3 sink $SSP0_MIXER_SINK_2 diff --git a/tools/topology/topology2/platform/intel/sdw-amp-generic.conf b/tools/topology/topology2/platform/intel/sdw-amp-generic.conf index 49aa3dd12cc4..9713b26e015b 100644 --- a/tools/topology/topology2/platform/intel/sdw-amp-generic.conf +++ b/tools/topology/topology2/platform/intel/sdw-amp-generic.conf @@ -33,8 +33,9 @@ Object.Pipeline { { index 20 - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name "sdw amplifiers" + pcm_id 2 } Object.Widget.gain.1 { Object.Control.mixer.1 { @@ -44,14 +45,12 @@ Object.Pipeline { } ] - mixout-gain-dai-copier-playback [ + mixout-gain-alh-dai-copier-playback [ { index 21 - Object.Widget.copier.1 { + Object.Widget.alh-copier.1 { stream_name $SDW_SPK_STREAM - dai_type "ALH" - copier_type "ALH" node_type $ALH_LINK_OUTPUT_CLASS } Object.Widget.gain.1 { @@ -64,43 +63,105 @@ Object.Pipeline { } -IncludeByKey.NUM_SDW_AMPS { +IncludeByKey.NUM_SDW_AMP_LINKS { "2" { Define { AMP_FEEDBACK_CH 4 } - Object.Pipeline { - io-gateway [ + Object.Widget { + alh-copier [ { - direction "playback" index $ALH_2ND_SPK_ID - copier_type "ALH" - Object.Widget.copier.1 { - stream_name $SDW_SPK_STREAM - dai_type "ALH" - copier_type "ALH" - type "dai_in" - node_type $ALH_LINK_OUTPUT_CLASS - } + type dai_in + stream_name $SDW_SPK_STREAM + dai_index 1 + type "dai_in" + direction "playback" + node_type $ALH_LINK_OUTPUT_CLASS + num_input_audio_formats 1 + num_output_audio_formats 1 + num_input_pins 1 + + # 32-bit 48KHz 2ch + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } - ] - io-gateway-capture [ { - direction "capture" index $ALH_2ND_SPK_IN_ID - copier_type "ALH" - - Object.Widget.copier.1 { - stream_name $SDW_SPK_IN_STREAM - dai_type "ALH" - copier_type "ALH" - type "dai_out" - node_type $ALH_LINK_INPUT_CLASS - } + type dai_out + stream_name $SDW_SPK_IN_STREAM + dai_index 1 + type "dai_out" + direction "capture" + node_type $ALH_LINK_INPUT_CLASS + num_input_audio_formats 1 + num_output_audio_formats 1 + num_output_pins 1 + + # 32-bit 48KHz 2ch + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + ] + pipeline [ + { + index $ALH_2ND_SPK_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + { + index $ALH_2ND_SPK_IN_ID + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] + # Add a virtual widget to connect the aggregated 2nd DAI copier + virtual [ + { + name 'virtual.sdw-amp' + type output + index $ALH_2ND_SPK_ID } ] } + + # Add the connection from the gain module to the aggregated 2nd DAI copier + # via the virtual widget. The virtual widget ensures that the routes between + # the gain and copier do not get established in the firmware. These are purely + # to show the existence of aggregation in the topology graph. + Object.Base.route [ + { + source "gain.21.1" + sink "virtual.sdw-amp" + } + { + source "virtual.sdw-amp" + sink "alh-copier.$SDW_SPK_STREAM.1" + } + ] } } @@ -123,12 +184,16 @@ Object.PCM.pcm [ Object.Base.route [ { source "gain.21.1" - sink "copier.ALH.21.1" + sink "alh-copier.$SDW_SPK_STREAM.0" } { source 'mixin.20.1' sink 'mixout.21.1' } + { + source 'host-copier.2.playback' + sink 'gain.20.1' + } ] IncludeByKey.SDW_AMP_FEEDBACK { @@ -154,28 +219,76 @@ IncludeByKey.SDW_AMP_FEEDBACK { { index 30 - Object.Widget.copier.1.stream_name "amp feedback" - Object.Widget.copier.1.Object.Base.audio_format.1 { - # 32 -> 16 bits conversion is done here, - # so in_bit_depth is 32 (and out_bit_depth is 16). - in_bit_depth 32 + Object.Widget.host-copier.1 { + stream_name "amp feedback" + pcm_id 3 + Object.Base.audio_format.1 { + # 32 -> 16 bits conversion is done here, + # so in_bit_depth is 32 (and out_bit_depth is 16). + in_bit_depth 32 + } } } ] - - io-gateway [ + } + Object.Widget { + alh-copier [ { - direction "capture" index 31 - copier_type "ALH" - - Object.Widget.copier.1 { - stream_name $SDW_SPK_IN_STREAM - dai_type "ALH" - copier_type "ALH" - type "dai_out" - node_type $ALH_LINK_INPUT_CLASS + type dai_out + stream_name $SDW_SPK_IN_STREAM + type "dai_out" + direction "capture" + node_type $ALH_LINK_INPUT_CLASS + num_input_audio_formats 1 + num_output_audio_formats 1 + num_output_pins 1 + + IncludeByKey.NUM_SDW_AMP_LINKS { + "2" { + Object.Base.input_audio_format [ + { + in_channels 4 + in_bit_depth 32 + in_valid_bit_depth 32 + in_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + in_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + Object.Base.output_audio_format [ + { + out_channels 4 + out_bit_depth 32 + out_valid_bit_depth 32 + out_ch_cfg $CHANNEL_CONFIG_3_POINT_1 + out_ch_map $CHANNEL_MAP_3_POINT_1 + } + ] + } + "1" { + # 32-bit 48KHz 2ch + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] } + } + } + ] + pipeline [ + { + index 31 + priority 0 + lp_mode 0 + dynamic_pipeline 1 } ] } @@ -198,8 +311,8 @@ IncludeByKey.SDW_AMP_FEEDBACK { ] Object.Base.route [ { - source "copier.ALH.31.1" - sink "copier.host.30.1" + source "alh-copier.$SDW_SPK_IN_STREAM.0" + sink "host-copier.3.capture" } ] } diff --git a/tools/topology/topology2/platform/intel/sdw-dmic-generic.conf b/tools/topology/topology2/platform/intel/sdw-dmic-generic.conf index 0a66cb90ac45..2d7e7e54f27f 100644 --- a/tools/topology/topology2/platform/intel/sdw-dmic-generic.conf +++ b/tools/topology/topology2/platform/intel/sdw-dmic-generic.conf @@ -27,26 +27,53 @@ Object.Pipeline { { index 40 - Object.Widget.copier.1.stream_name "sdw dmic" - Object.Widget.copier.1.Object.Base.audio_format.1 { - # 32 -> 16 bits conversion is done here, - # so in_bit_depth is 32 (and out_bit_depth is 16). - in_bit_depth 32 + Object.Widget.host-copier.1 { + stream_name "sdw dmic" + pcm_id 4 + Object.Base.audio_format.1 { + # 32 -> 16 bits conversion is done here, + # so in_bit_depth is 32 (and out_bit_depth is 16). + in_bit_depth 32 + } } } ] - io-gateway-capture [ +} + +Object.Widget { + alh-copier [ { - direction "capture" index 41 - copier_type "ALH" - Object.Widget.copier.1 { - stream_name $SDW_DMIC_STREAM - dai_type "ALH" - copier_type "ALH" - type "dai_out" - node_type $ALH_LINK_INPUT_CLASS - } + type dai_out + stream_name $SDW_DMIC_STREAM + type "dai_out" + direction "capture" + node_type $ALH_LINK_INPUT_CLASS + num_input_audio_formats 1 + num_output_audio_formats 1 + num_output_pins 1 + + # 32-bit 48KHz 2ch + Object.Base.input_audio_format [ + { + in_bit_depth 32 + in_valid_bit_depth 32 + } + ] + Object.Base.output_audio_format [ + { + out_bit_depth 32 + out_valid_bit_depth 32 + } + ] + } + ] + pipeline [ + { + index 41 + priority 0 + lp_mode 0 + dynamic_pipeline 1 } ] } @@ -69,7 +96,7 @@ Object.PCM.pcm [ Object.Base.route [ { - source "copier.ALH.41.1" - sink "copier.host.40.1" + source "alh-copier.$SDW_DMIC_STREAM.0" + sink "host-copier.4.capture" } ] diff --git a/tools/topology/topology2/platform/intel/sdw-jack-generic.conf b/tools/topology/topology2/platform/intel/sdw-jack-generic.conf new file mode 100644 index 000000000000..62fdc7fed377 --- /dev/null +++ b/tools/topology/topology2/platform/intel/sdw-jack-generic.conf @@ -0,0 +1,195 @@ +# include deep buffer config if buffer size is in 1 - 1000 ms. +IncludeByKey.DEEPBUFFER_FW_DMA_MS { + "([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|1000)" "platform/intel/deep-buffer.conf" +} + +# +# List of all DAIs +# +Object.Dai.ALH [ + { + dai_index 0 + id $SDW_JACK_OUT_BE_ID + direction "playback" + name $SDW_JACK_OUT_STREAM + default_hw_conf_id 0 + rate 48000 + channels 2 + + Object.Base.hw_config.1 { + id 0 + name "ALH2" + } + } + { + dai_index 10 + id $SDW_JACK_IN_BE_ID + direction "capture" + name $SDW_JACK_IN_STREAM + default_hw_conf_id 0 + rate 48000 + channels 2 + + Object.Base.hw_config.1 { + id 0 + name "ALH3" + } + } +] + +# +# Pipeline definitions +# + +Object.Pipeline { + host-copier-gain-mixin-playback [ + { + index 0 + + Object.Widget.host-copier.1 { + stream_name "volume playback 0" + pcm_id 0 + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name '1 Playback Volume 0' + } + } + } + ] + + mixout-gain-alh-dai-copier-playback [ + { + index 1 + + Object.Widget.alh-copier.1 { + stream_name $SDW_JACK_OUT_STREAM + node_type $ALH_LINK_OUTPUT_CLASS + } + Object.Widget.gain.1 { + Object.Control.mixer.1 { + name '2 Main Playback Volume' + } + } + } + ] + + host-gateway-capture [ + { + index 10 + + Object.Widget.host-copier.1 { + stream_name "Passthrough Capture 0" + pcm_id 1 + Object.Base.audio_format.1 { + # 32/32 -> 16/16 bits conversion is done here + in_bit_depth 32 + in_valid_bit_depth 32 + } + } + } + ] +} + +# Jack capture pipeline widgets +Object.Widget { + alh-copier [ + { + stream_name $SDW_JACK_IN_STREAM + direction "capture" + type "dai_out" + index 11 + node_type $ALH_LINK_INPUT_CLASS + num_input_audio_formats 1 + num_output_audio_formats 1 + num_output_pins 1 + + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + } + ] + + eqiir [ + { + num_input_audio_formats 1 + num_output_audio_formats 1 + index 11 + Object.Base.audio_format.1 { + in_bit_depth 32 + in_valid_bit_depth 32 + out_bit_depth 32 + out_valid_bit_depth 32 + } + + Object.Control.bytes."1" { + + name '4 Main capture Iir Eq' + } + } + ] + + pipeline [ + { + index 11 + priority 0 + lp_mode 0 + dynamic_pipeline 1 + } + ] +} + +Object.PCM.pcm [ + { + name "Jack out" + id 0 + direction "playback" + Object.Base.fe_dai.1 { + name "Jack out" + } + + Object.PCM.pcm_caps.1 { + name "volume playback 0" + formats 'S16_LE,S32_LE' + } + } + { + name "Jack in" + id 1 + direction "capture" + Object.Base.fe_dai.1 { + name "Jack in" + } + + Object.PCM.pcm_caps.1 { + name "Passthrough Capture 0" + formats 'S16_LE,S32_LE' + } + } +] + +Object.Base.route [ + { + source "gain.1.1" + sink "alh-copier.$SDW_JACK_OUT_STREAM.0" + } + { + source "mixin.0.1" + sink "mixout.1.1" + } + { + source "alh-copier.$SDW_JACK_IN_STREAM.0" + sink "eqiir.11.0" + } + { + source "eqiir.11.0" + sink "host-copier.1.capture" + } + { + source "host-copier.0.playback" + sink "gain.0.1" + } +] diff --git a/tools/topology/topology2/platform/intel/speaker-echo-ref.conf b/tools/topology/topology2/platform/intel/speaker-echo-ref.conf index 3926712264d8..0fba6b61326f 100644 --- a/tools/topology/topology2/platform/intel/speaker-echo-ref.conf +++ b/tools/topology/topology2/platform/intel/speaker-echo-ref.conf @@ -7,8 +7,9 @@ Object.Pipeline { { index $ECHO_REF_HOST_PIPELINE_ID - Object.Widget.copier.1 { + Object.Widget.host-copier.1 { stream_name $ECHO_REF_STREAM_NAME + pcm_id 27 } } ] @@ -56,6 +57,6 @@ Object.Base.route [ } { source $ECHO_REF_COPIER_MODULE - sink $ECHO_REF_HOST_PIPELINE_SINK + sink "host-copier.27.capture" } ] diff --git a/tools/topology/topology2/sof-ace-tplg/tplg-targets.cmake b/tools/topology/topology2/sof-ace-tplg/tplg-targets.cmake index 2d2eaf4d5cb2..99c54d15febe 100644 --- a/tools/topology/topology2/sof-ace-tplg/tplg-targets.cmake +++ b/tools/topology/topology2/sof-ace-tplg/tplg-targets.cmake @@ -3,31 +3,42 @@ # Array of "input-file-name;output-file-name;comma separated pre-processor variables" set(TPLGS # HDMI only topology with passthrough pipelines -"sof-hda-generic\;sof-hda-generic-idisp\;USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100" +"sof-hda-generic\;sof-hda-generic-idisp\;USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100,\ +DEEPBUFFER_D0I3_COMPATIBLE=true" # HDA topology with mixer-based pipelines for HDA and passthrough pipelines for HDMI -"sof-hda-generic\;sof-hda-generic\;HDA_CONFIG=mix,USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100" +"sof-hda-generic\;sof-hda-generic\;HDA_CONFIG=mix,USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100,\ +DEEPBUFFER_D0I3_COMPATIBLE=true" # If the alsatplg plugins for NHLT are not available, the NHLT blobs will not be added to the # topologies below. "sof-hda-generic\;sof-hda-generic-4ch\;PLATFORM=mtl,\ HDA_CONFIG=mix,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,PREPROCESS_PLUGINS=nhlt,\ -NHLT_BIN=nhlt-sof-hda-generic-4ch.bin,USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100" +NHLT_BIN=nhlt-sof-hda-generic-4ch.bin,USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100,\ +DEEPBUFFER_D0I3_COMPATIBLE=true" "sof-hda-generic\;sof-hda-generic-2ch\;PLATFORM=mtl,\ HDA_CONFIG=mix,NUM_DMICS=2,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-hda-generic-2ch.bin,\ -USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100" +USE_CHAIN_DMA=true,DEEPBUFFER_FW_DMA_MS=100,DEEPBUFFER_D0I3_COMPATIBLE=true" # SDW + DMIC topology with passthrough pipelines # We will change NUM_HDMIS to 3 once HDMI is enabled on MTL RVP -"cavs-sdw\;sof-mtl-rt711-4ch\;PLATFORM=mtl,NUM_DMICS=4,DMIC0_ID=2,DMIC1_ID=3,NUM_HDMIS=0,\ -PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-rt711-4ch.bin,DEEPBUFFER_FW_DMA_MS=100" +"cavs-sdw\;sof-mtl-rt711-4ch\;PLATFORM=mtl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,PDM1_MIC_B_ENABLE=1,\ +DMIC0_ID=2,DMIC1_ID=3,NUM_HDMIS=0,PREPROCESS_PLUGINS=nhlt,NHLT_BIN=nhlt-sof-mtl-rt711-4ch.bin,\ +DEEPBUFFER_FW_DMA_MS=100,DEEPBUFFER_D0I3_COMPATIBLE=true" + +"cavs-sdw\;sof-mtl-rt711-l0-rt1316-l23-rt714-l1\;PLATFORM=mtl,NUM_SDW_AMP_LINKS=2,SDW_DMIC=1,\ +NUM_HDMIS=0,SDW_SPK_STREAM=SDW2-Playback,SDW_SPK_IN_STREAM=SDW2-Capture,SDW_DMIC_STREAM=SDW1-Capture" + +# Below topologies are used on Chromebooks "cavs-rt5682\;sof-mtl-max98357a-rt5682\;PLATFORM=mtl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ PDM1_MIC_B_ENABLE=1,DMIC0_PCM_ID=99,PREPROCESS_PLUGINS=nhlt,\ NHLT_BIN=nhlt-sof-mtl-max98357a-rt5682.bin,DEEPBUFFER_FW_DMA_MS=10,INCLUDE_ECHO_REF=true,\ -BT_NAME=SSP2-BT,BT_ID=8,BT_PCM_NAME=Bluetooth" +BT_NAME=SSP2-BT,BT_ID=8,BT_PCM_NAME=Bluetooth,USE_CHAIN_DMA=true,DEEPBUFFER_D0I3_COMPATIBLE=true,\ +GOOGLE_RTC_AEC_SUPPORT=1" "cavs-rt5682\;sof-mtl-max98357a-rt5682-ssp2-ssp0\;PLATFORM=mtl,NUM_DMICS=4,PDM1_MIC_A_ENABLE=1,\ PDM1_MIC_B_ENABLE=1,DMIC0_PCM_ID=99,PREPROCESS_PLUGINS=nhlt,\ NHLT_BIN=nhlt-sof-mtl-max98357a-rt5682.bin,DEEPBUFFER_FW_DMA_MS=10,HEADSET_SSP_DAI_INDEX=2,\ SPEAKER_SSP_DAI_INDEX=0,HEADSET_CODEC_NAME=SSP2-Codec,SPEAKER_CODEC_NAME=SSP0-Codec,\ -BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=8,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true" +BT_NAME=SSP1-BT,BT_INDEX=1,BT_ID=8,BT_PCM_NAME=Bluetooth,INCLUDE_ECHO_REF=true,USE_CHAIN_DMA=true,\ +DEEPBUFFER_D0I3_COMPATIBLE=true" ) diff --git a/tools/tplg_parser/include/tplg_parser/tokens.h b/tools/tplg_parser/include/tplg_parser/tokens.h index 9ba6b38dbb00..e6c63f015b04 100644 --- a/tools/tplg_parser/include/tplg_parser/tokens.h +++ b/tools/tplg_parser/include/tplg_parser/tokens.h @@ -18,6 +18,7 @@ #define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44 #endif +#include #include struct sof_topology_token { diff --git a/tools/tplg_parser/include/tplg_parser/topology.h b/tools/tplg_parser/include/tplg_parser/topology.h index 0899c2320d01..5194f5780bfa 100644 --- a/tools/tplg_parser/include/tplg_parser/topology.h +++ b/tools/tplg_parser/include/tplg_parser/topology.h @@ -22,6 +22,7 @@ #define SNDRV_CTL_ELEM_ID_NAME_MAXLEN 44 #endif +#include #include #define TPLG_PARSER_SOF_DEV 1 @@ -85,7 +86,7 @@ struct tplg_context { ({struct snd_soc_tplg_hdr *ptr; \ ptr = (struct snd_soc_tplg_hdr *)(ctx->tplg_base + ctx->tplg_offset); \ if (ptr->size != sizeof(*ptr)) { \ - printf("%s %d hdr size mismatch 0x%x:0x%lx at offset %ld\n", \ + printf("%s %d hdr size mismatch 0x%x:0x%zx at offset %ld\n", \ __func__, __LINE__, ptr->size, sizeof(*ptr), \ ctx->tplg_offset); assert(0); \ } \ diff --git a/tools/tune/dmic/dmic_batch.m b/tools/tune/dmic/dmic_batch.m index c93ded424454..b2be24d53c9e 100644 --- a/tools/tune/dmic/dmic_batch.m +++ b/tools/tune/dmic/dmic_batch.m @@ -27,25 +27,31 @@ prm.pdm(2).polarity_mic_b = 0; prm.pdm(2).clk_edge = 0; prm.pdm(2).skew = 0; +prm.vfn = {}; %% Design prm.pdmclk_min = 2.4e6; prm.pdmclk_max = 4.8e6; +%% alsa-utils +if exist('include_alsa_utils', 'dir') == 7 + rmdir('include_alsa_utils', 's'); +end + % clkdiv, mcic, mfira, mfirb -prm.fifo_a_fs = 8e3; prm.fifo_b_fs = 16e3; dmic_init(prm); % 8, 30, 10, 5 -prm.fifo_a_fs = 8e3; prm.fifo_b_fs = 32e3; dmic_init(prm); % 8, 25, 12, 3 -prm.fifo_a_fs = 8e3; prm.fifo_b_fs = 48e3; dmic_init(prm); % 8, 25, 12, 2 -prm.fifo_a_fs = 24e3; prm.fifo_b_fs = 96e3; dmic_init(prm); % 5, 20, 8, 2 -prm.fifo_a_fs = 32e3; prm.fifo_b_fs = 96e3; dmic_init(prm); % 5, 20, 6, 2 -prm.fifo_a_fs = 48e3; prm.fifo_b_fs = 96e3; dmic_init(prm); % 5, 20, 4, 2 -prm.fifo_a_fs = 48e3; prm.fifo_b_fs = 16e3; dmic_init(prm); % 8, 25, 2, 6 +prm.fifo_a_fs = 8e3; prm.fifo_b_fs = 16e3; prm = dmic_init(prm); % 8, 30, 10, 5 +prm.fifo_a_fs = 8e3; prm.fifo_b_fs = 32e3; prm = dmic_init(prm); % 8, 25, 12, 3 +prm.fifo_a_fs = 8e3; prm.fifo_b_fs = 48e3; prm = dmic_init(prm); % 8, 25, 12, 2 +prm.fifo_a_fs = 24e3; prm.fifo_b_fs = 96e3; prm = dmic_init(prm); % 5, 20, 8, 2 +prm.fifo_a_fs = 32e3; prm.fifo_b_fs = 96e3; prm = dmic_init(prm); % 5, 20, 6, 2 +prm.fifo_a_fs = 48e3; prm.fifo_b_fs = 96e3; prm = dmic_init(prm); % 5, 20, 4, 2 +prm.fifo_a_fs = 48e3; prm.fifo_b_fs = 16e3; prm = dmic_init(prm); % 8, 25, 2, 6 %% No need to run due to duplicated FIR coefficients -%prm.fifo_a_fs = 8e3; prm.fifo_b_fs = 24e3; dmic_init(prm); % 8, 25, 12, 4 -%prm.fifo_a_fs = 16e3; prm.fifo_b_fs = 32e3; dmic_init(prm); % 8, 25, 6, 3 -%prm.fifo_a_fs = 16e3; prm.fifo_b_fs = 24e3; dmic_init(prm); % 8, 25, 6, 4 -%prm.fifo_a_fs = 16e3; prm.fifo_b_fs = 96e3; dmic_init(prm); % 5, 20, 12, 2 -%prm.fifo_a_fs = 24e3; prm.fifo_b_fs = 32e3; dmic_init(prm); % 8, 25, 4, 3 -%prm.fifo_a_fs = 24e3; prm.fifo_b_fs = 48e3; dmic_init(prm); % 8, 25, 4, 2 -%prm.fifo_a_fs = 32e3; prm.fifo_b_fs = 48e3; dmic_init(prm); % 5, 20, 6, 4 +%prm.fifo_a_fs = 8e3; prm.fifo_b_fs = 24e3; prm = dmic_init(prm); % 8, 25, 12, 4 +%prm.fifo_a_fs = 16e3; prm.fifo_b_fs = 32e3; prm = dmic_init(prm); % 8, 25, 6, 3 +%prm.fifo_a_fs = 16e3; prm.fifo_b_fs = 24e3; prm = dmic_init(prm); % 8, 25, 6, 4 +%prm.fifo_a_fs = 16e3; prm.fifo_b_fs = 96e3; prm = dmic_init(prm); % 5, 20, 12, 2 +%prm.fifo_a_fs = 24e3; prm.fifo_b_fs = 32e3; prm = dmic_init(prm); % 8, 25, 4, 3 +%prm.fifo_a_fs = 24e3; prm.fifo_b_fs = 48e3; prm = dmic_init(prm); % 8, 25, 4, 2 +%prm.fifo_a_fs = 32e3; prm.fifo_b_fs = 48e3; prm = dmic_init(prm); % 5, 20, 6, 4 diff --git a/tools/tune/dmic/dmic_fir_export_alsa.m b/tools/tune/dmic/dmic_fir_export_alsa.m new file mode 100644 index 000000000000..65c37b331927 --- /dev/null +++ b/tools/tune/dmic/dmic_fir_export_alsa.m @@ -0,0 +1,102 @@ +% dmic_fir_export - Export FIR coefficients +% +% vfn_arr = pdm_export_coef(fir, hdir, prev_vfn_arr) +% +% fir - fir definition struct +% hdir - directory for header files + +% SPDX-License-Identifier: BSD-3-Clause +% +% Copyright (c) 2023, Intel Corporation. All rights reserved. +% +% Author: Seppo Ingalsuo + +function vfn_arr = dmic_fir_export_alsa(fir, hdir, prev_vfn_arr) + +if ~exist(hdir, 'dir') + mkdir(hdir); +end + +pbi = round(fir.cp * 1e4); +sbi = round(fir.cs * 1e4); +rpi = round(fir.rp * 1e2); +rsi = round(fir.rs); + +hfn = sprintf('%s/pdm-decim-fir.h', hdir); +vfn = sprintf('fir_int32_%02d_%04d_%04d_%03d_%03d', fir.m, pbi, sbi, rpi, rsi); +sfn = sprintf('pdm_decim_int32_%02d_%04d_%04d_%03d_%03d', fir.m, pbi, sbi, rpi, rsi); + +fprintf('Exporting %s ...\n', hfn); + +if exist(hfn, 'file') == 2 + % Avoid to export duplicate + if max(ismember(prev_vfn_arr, vfn)) > 0 + vfn_arr = prev_vfn_arr; + return + else + fh = fopen(hfn, 'a'); + vfn_arr = [prev_vfn_arr; vfn]; + end +else + fh = fopen(hfn, 'w'); + fprintf(fh, '// SPDX-License-Identifier: BSD-3-Clause\n'); + fprintf(fh, '//\n'); + fprintf(fh, '// Copyright(c) 2021-2023 Intel Corporation. All rights reserved.\n'); + fprintf(fh, '//\n'); + fprintf(fh, '// Author: Seppo Ingalsuo \n'); + fprintf(fh, '// Jaska Uimonen \n\n'); + fprintf(fh, '#ifndef __SOF_AUDIO_COEFFICIENTS_PDM_DECIM_PDM_DECIM_FIR_H__\n'); + fprintf(fh, '#define __SOF_AUDIO_COEFFICIENTS_PDM_DECIM_PDM_DECIM_FIR_H__\n\n'); + fprintf(fh, '#include \n\n'); + fprintf(fh, 'struct pdm_decim {\n'); + fprintf(fh, ' int decim_factor;\n'); + fprintf(fh, ' int length;\n'); + fprintf(fh, ' int shift;\n'); + fprintf(fh, ' int relative_passband;\n'); + fprintf(fh, ' int relative_stopband;\n'); + fprintf(fh, ' int passband_ripple;\n'); + fprintf(fh, ' int stopband_ripple;\n'); + fprintf(fh, ' const int32_t *coef;\n'); + fprintf(fh, '};\n'); + vfn_arr = { vfn }; +end + +print_int_coef(fir, fh, 'int32_t', vfn); + +fprintf(fh, '\n\n'); +fprintf(fh, 'struct pdm_decim %s = {\n', sfn); +fprintf(fh, '\t%d, %d, %d, %d, %d, %d, %d, %s\n};\n', ... + fir.m, fir.length, fir.shift, pbi, sbi, rpi, rsi, vfn); +fclose(fh); + +end + +function print_int_coef(fir, fh, vtype, vfn) + +coefs_per_line = 5; +n = 1; + +fprintf(fh, '\n'); +fprintf(fh, 'const %s %s[%d] = {\n', ... + vtype, vfn, fir.length); + +while n <= fir.length + fprintf(fh, '\t'); + nremain = fir.length - n + 1; + ncoef = min(coefs_per_line, nremain); + for i = 1 : ncoef + fprintf(fh,'%d', fir.coef(n)); + if n < fir.length + fprintf(fh, ','); + if i < ncoef + fprintf(fh, ' '); + end + end + n = n + 1; + end + fprintf(fh, '\n'); +end +fprintf(fh,'};'); + +end + diff --git a/tools/tune/dmic/dmic_init.m b/tools/tune/dmic/dmic_init.m index 1d956fde8d07..b1192b2bffca 100644 --- a/tools/tune/dmic/dmic_init.m +++ b/tools/tune/dmic/dmic_init.m @@ -1,4 +1,4 @@ -% success = dmic_init(prm) +% prm = dmic_init(prm) % % Create PDM microphones interface configuration @@ -8,7 +8,7 @@ % % Author: Seppo Ingalsuo -function success = dmic_init(prm) +function prm = dmic_init(prm) hw.controllers = 4; hw.bits_cic = 26; @@ -18,7 +18,6 @@ hw.bits_fir_output = 24; hw.bits_fir_internal = 26; hw.bits_gain_output = 22; -hw.fir_length_max = 250; hw.cic_shift_right_range = [-8 4]; hw.fir_shift_right_range = [0 8]; hw.fir_max_length = 250; @@ -31,7 +30,6 @@ spec.cp = 0.4375; spec.cs = 0.5100; spec.rs = 95; -success = 0; if (prm.fifo_a_fs == 0) && (prm.fifo_b_fs == 0) fprintf(1,'Error: At least one FIFO needs non-zero Fs!\n'); @@ -54,60 +52,31 @@ %% Done, print 1st modes combination fprintf('Selected fifo_a_fs=%d, fifo_b_fs=%d: ', prm.fifo_a_fs, prm.fifo_b_fs); cfg = select_mode(common_mcic_list, a_mfir_list, b_mfir_list, common_clkdiv_list, cfg); -cfg = get_cic_config(prm, cfg, hw); -cfg = get_fir_config(prm, cfg, hw, spec); +cfg = get_cic_config(cfg, hw); +prm = get_fir_config(prm, cfg, hw, spec); end %% Functions %% Get FIR filters -function cfg = get_fir_config(prm, cfg, hw, spec) +function prm = get_fir_config(prm, cfg, hw, spec) if prm.fifo_a_fs > 0 - [coef, shift] = get_fir(cfg.mfir_a, prm, cfg, hw, spec); - - [cfg.fir_coef_a, cfg.fir_shift_a, cfg.fir_length_a] = ... - scale_fir_coef(coef, shift, spec.scale, cfg.remain_gain_to_fir, hw.bits_fir_coef); - cfg.fir_gain_a = 1; -else - cfg.fir_gain_a = 0; - cfg.fir_coef_a = 0; - cfg.fir_shift_a = 0; - cfg.fir_length_a = 1; + fir = get_fir(cfg.mfir_a, cfg, hw, spec); + dmic_fir_export(fir, 'include'); + prm.vfn = dmic_fir_export_alsa(fir, 'include_alsa_utils', prm.vfn); end if prm.fifo_b_fs > 0 - [coef, shift] = get_fir(cfg.mfir_b, prm, cfg, hw, spec); - - [cfg.fir_coef_b, cfg.fir_shift_b, cfg.fir_length_b] = ... - scale_fir_coef(coef, shift, spec.scale, cfg.remain_gain_to_fir, hw.bits_fir_coef); - cfg.fir_gain_b = 1; -else - cfg.fir_gain_b = 0; - cfg.fir_coef_b = 0; - cfg.fir_shift_b = 0; - cfg.fir_length_b = 1; + fir = get_fir(cfg.mfir_b, cfg, hw, spec); + dmic_fir_export(fir, 'include'); + prm.vfn = dmic_fir_export_alsa(fir, 'include_alsa_utils', prm.vfn); end end -function [coefq, shiftq, len] = scale_fir_coef(coef32, shift32, hw_sens, add_gain, bits) - -out_scale = 2^(bits-1); -q31_scale = 2^31; -coef = coef32/q31_scale * 2^(-shift32) * hw_sens * add_gain; -max_abs_coef = max(abs(coef)); -scale = 0.9999/max_abs_coef; -shiftq = floor(log(scale)/log(2)); -c = 2^shiftq; -coefq = round(out_scale * coef * c); -len = length(coefq); - -end - -% This function becomes table lookup in C -function [coef32, shift] = get_fir(mfir, prm, cfg, hw, spec) +function fir = get_fir(mfir, cfg, hw, spec) fs_fir = cfg.mic_clk/cfg.mcic; fs = fs_fir/mfir; @@ -136,7 +105,6 @@ fir.rp = spec.rp; fir.rs = rs; fir.m = mfir; -dmic_fir_export(fir, 'include'); end @@ -156,7 +124,7 @@ % Find common mode with lowest FIR decimation ratio. If there are many % select one with lowest mic clock rate. Lowest rates or highest dividers % are in the end of list. -if length(common_mcic_list) > 0 +if ~isempty(common_mcic_list) for mtry = mpref idx = find(a_mfir_list == mtry); if ~isempty(idx) @@ -179,7 +147,7 @@ end %% Compute CIC filter settings -function cfg = get_cic_config(prm, cfg, hw) +function cfg = get_cic_config(cfg, hw) cfg.mic_clk = hw.ioclk/cfg.clk_div; g_cic = cfg.mcic^5; @@ -190,12 +158,12 @@ fprintf(1,'Error: Needed CIC word length is exceeded %d\n', bitsneeded); end -if cfg.cic_shift < hw.cic_shift_right_range(1); +if cfg.cic_shift < hw.cic_shift_right_range(1) fprintf(1,'Warning: Limited CIC shift right from %d', cfg.cic_shift); cfg.cic_shift = hw.cic_shift_right_range(1); end -if cfg.cic_shift > hw.cic_shift_right_range(2); +if cfg.cic_shift > hw.cic_shift_right_range(2) fprintf(1,'Error: Limited CIC shift right from %d', cfg.cic_shift); cfg.cic_shift = hw.cic_shift_right_range(2); end diff --git a/versions.json b/versions.json new file mode 100644 index 000000000000..6d63ce0e079a --- /dev/null +++ b/versions.json @@ -0,0 +1,6 @@ +{ + "SOF": { + "MAJOR": "2", + "MINOR": "5" + } +} diff --git a/west.yml b/west.yml index ef61809499c5..2eb2994bf226 100644 --- a/west.yml +++ b/west.yml @@ -34,7 +34,7 @@ manifest: - name: rimage repo-path: rimage path: sof/rimage - revision: 9643a986dda97c6cb339d5c75c0eaa178d8317da + revision: ab0429fdbe563ef6abe499c69b2483e96c4762d0 - name: tomlc99 repo-path: tomlc99 @@ -43,7 +43,7 @@ manifest: - name: zephyr repo-path: zephyr - revision: 1851950977d5c89d8727e1058a5732f71ce4cd2a + revision: 7d54586751cfe405d2cdcfd850f8100bc9844f63 remote: zephyrproject # Import some projects listed in zephyr/west.yml@revision diff --git a/xtos/include/sof/compiler_attributes.h b/xtos/include/sof/compiler_attributes.h index 3eb5a45e1a7b..30ccaff1fe15 100644 --- a/xtos/include/sof/compiler_attributes.h +++ b/xtos/include/sof/compiler_attributes.h @@ -7,6 +7,8 @@ #ifdef __ZEPHYR__ +#include + /* Get __sparse_cache and __sparse_force definitions if __CHECKER__ is defined */ #include diff --git a/xtos/include/sof/lib/dma.h b/xtos/include/sof/lib/dma.h index bd207ce42025..30fa889699bb 100644 --- a/xtos/include/sof/lib/dma.h +++ b/xtos/include/sof/lib/dma.h @@ -532,6 +532,15 @@ int dma_buffer_copy_from(struct comp_buffer __sparse_cache *source, struct comp_buffer __sparse_cache *sink, dma_process_func process, uint32_t source_bytes); +/* + * Used when copying DMA buffer bytes into multiple sink buffers, one at a time using the provided + * conversion function. DMA buffer consume should be performed after the data has been copied + * to all sinks. + */ +int dma_buffer_copy_from_no_consume(struct comp_buffer __sparse_cache *source, + struct comp_buffer __sparse_cache *sink, + dma_process_func process, uint32_t source_bytes); + /* copies data to DMA buffer using provided processing function */ int dma_buffer_copy_to(struct comp_buffer __sparse_cache *source, struct comp_buffer __sparse_cache *sink, diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index 82ccb02020d1..90b8be8c20bf 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -46,7 +46,8 @@ endfunction() zephyr_interface_library_named(SOF) # SOF source paths. -set(SOF_SRC_PATH "../src") +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") @@ -86,18 +87,18 @@ ExternalProject_Add(sof_logger_ep ) # default SOF includes -target_include_directories(SOF INTERFACE ../rimage/src/include) +target_include_directories(SOF INTERFACE ${sof_top_dir}/rimage/src/include) target_include_directories(SOF INTERFACE ${SOF_SRC_PATH}/include) target_include_directories(SOF INTERFACE ${SOF_SRC_PATH}/arch/${ARCH}/include) -target_include_directories(SOF INTERFACE ${SOF_SRC_PATH}/../third_party/include) +target_include_directories(SOF INTERFACE ${sof_top_dir}/third_party/include) # TODO: Zephyr should not need xtos headers: FIX. if (CONFIG_SOF_ZEPHYR_STRICT_HEADERS) - target_include_directories(SOF INTERFACE ${SOF_SRC_PATH}/../zephyr/include) + target_include_directories(SOF INTERFACE ${sof_top_dir}/zephyr/include) else() # include Zephyr before xtos to flag up any errors in SOF - target_include_directories(SOF INTERFACE ${SOF_SRC_PATH}/../zephyr/include) - target_include_directories(SOF INTERFACE ${SOF_SRC_PATH}/../xtos/include) + target_include_directories(SOF INTERFACE ${sof_top_dir}/zephyr/include) + target_include_directories(SOF INTERFACE ${sof_top_dir}/xtos/include) endif() # SOF module init @@ -207,7 +208,7 @@ if (CONFIG_SOC_SERIES_INTEL_CAVS_V25) endif() # Intel ACE 1.5 and newer platforms -if (CONFIG_ACE_VERSION_1_5) +if (CONFIG_SOC_SERIES_INTEL_ACE) # Driver sources zephyr_library_sources( @@ -217,12 +218,23 @@ if (CONFIG_ACE_VERSION_1_5) # Platform sources zephyr_library_sources( ${SOF_PLATFORM_PATH}/intel/ace/platform.c - ${SOF_PLATFORM_PATH}/meteorlake/lib/clk.c lib/pm_runtime.c lib/clk.c lib/dma.c ) + if (CONFIG_SOC_INTEL_ACE15_MTPM) + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/meteorlake/lib/clk.c + ) + endif() + + if (CONFIG_SOC_INTEL_ACE20_LNL) + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/lunarlake/lib/clk.c + ) + endif() + # SOF core infrastructure - runs on top of Zephyr zephyr_library_sources( ${SOF_SRC_PATH}/schedule/zephyr_ll.c @@ -245,10 +257,13 @@ if (CONFIG_ACE_VERSION_1_5) ${SOF_PLATFORM_PATH}/intel/ace/lib/watchdog.c ) - set(PLATFORM "meteorlake") - + if (CONFIG_SOC_INTEL_ACE15_MTPM) + set(PLATFORM "meteorlake") + elseif(CONFIG_SOC_INTEL_ACE20_LNL) + set(PLATFORM "lunarlake") + endif() zephyr_include_directories(${SOF_PLATFORM_PATH}/intel/ace/include) - zephyr_include_directories(${SOF_PLATFORM_PATH}/meteorlake/include) + zephyr_include_directories(${SOF_PLATFORM_PATH}/${PLATFORM}/include) endif() # NXP IMX8 platforms @@ -309,6 +324,30 @@ if (CONFIG_SOC_SERIES_NXP_IMX8M) set(PLATFORM "imx8m") endif() +if (CONFIG_SOC_SERIES_MIMX9_A55) + # Platform sources + zephyr_library_sources( + ${SOF_PLATFORM_PATH}/imx93_a55/platform.c + ${SOF_PLATFORM_PATH}/imx93_a55/lib/clk.c + ${SOF_PLATFORM_PATH}/imx93_a55/lib/dma.c + ${SOF_PLATFORM_PATH}/imx93_a55/lib/dai.c + ) + + # Drivers + zephyr_library_sources( + ${SOF_DRIVERS_PATH}/generic/dummy-dma.c + ${SOF_DRIVERS_PATH}/imx/ipc.c + ${SOF_DRIVERS_PATH}/imx/edma.c + ${SOF_DRIVERS_PATH}/imx/sai.c + ) + + zephyr_library_sources( + ${SOF_SRC_PATH}/schedule/zephyr_ll.c + ) + + set(PLATFORM "imx93_a55") +endif() + # Building for native_posix-based whole-OS host emulator zephyr_library_sources_ifdef(CONFIG_ZEPHYR_POSIX ${SOF_SRC_PATH}/schedule/zephyr_ll.c @@ -511,7 +550,7 @@ else() endif() zephyr_library_sources_ifdef(CONFIG_IPC4_GATEWAY - ${SOF_AUDIO_PATH}/ipcgtw.c + ${SOF_AUDIO_PATH}/copier/copier_ipcgtw.c ) zephyr_library_sources_ifdef(CONFIG_SAMPLE_KEYPHRASE @@ -634,9 +673,15 @@ zephyr_library_sources_ifdef(CONFIG_COMP_RTNR ${SOF_AUDIO_PATH}/rtnr/rtnr.c ) -zephyr_library_sources_ifdef(CONFIG_SAMPLE_SMART_AMP - ${SOF_SAMPLES_PATH}/audio/smart_amp_test.c -) +if(CONFIG_IPC_MAJOR_3) + zephyr_library_sources_ifdef(CONFIG_SAMPLE_SMART_AMP + ${SOF_SAMPLES_PATH}/audio/smart_amp_test_ipc3.c + ) +elseif(CONFIG_IPC_MAJOR_4) + zephyr_library_sources_ifdef(CONFIG_SAMPLE_SMART_AMP + ${SOF_SAMPLES_PATH}/audio/smart_amp_test_ipc4.c + ) +endif() zephyr_library_sources_ifdef(CONFIG_COMP_TDFB ${SOF_AUDIO_PATH}/tdfb/tdfb.c @@ -690,6 +735,7 @@ zephyr_library_sources_ifdef(CONFIG_HAVE_AGENT zephyr_library_sources_ifdef(CONFIG_AMS ${SOF_LIB_PATH}/ams.c + ${SOF_IPC_PATH}/ipc4/ams_helpers.c ) zephyr_library_sources_ifdef(CONFIG_GDB_DEBUG @@ -705,7 +751,7 @@ zephyr_library_link_libraries(SOF) target_link_libraries(SOF INTERFACE zephyr_interface) # Setup SOF directories -set(SOF_ROOT_SOURCE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/..) +set(SOF_ROOT_SOURCE_DIRECTORY ${sof_top_dir}) set(SOF_ROOT_BINARY_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) # This generated/ directory is shared with Zephyr. diff --git a/zephyr/Kconfig b/zephyr/Kconfig index c9dda09a9f53..86c94a1de9a4 100644 --- a/zephyr/Kconfig +++ b/zephyr/Kconfig @@ -34,12 +34,22 @@ config DMA_DOMAIN help This enables the usage of the DMA domain in scheduling. +config DMA_DOMAIN_SEM_LIMIT + int "Number of resources the Zephyr's DMA domain can accumulate" + depends on DMA_DOMAIN + default 10 + help + Set this value according to the load of the system. Please make sure + that SEM_LIMIT covers the maximum number of tasks your system will be + executing at some point (worst case). + config ZEPHYR_DP_SCHEDULER bool "use Zephyr thread based DP scheduler" default y if ACE default n depends on IPC_MAJOR_4 depends on ZEPHYR_SOF_MODULE + depends on ACE help Enable Data Processing preemptive scheduler based on Zephyr preemptive threads. diff --git a/zephyr/docker-run.sh b/zephyr/docker-run.sh index 24aedddd7385..bf1c37a46cdc 100755 --- a/zephyr/docker-run.sh +++ b/zephyr/docker-run.sh @@ -18,10 +18,10 @@ # use this script with a image other than the one officially tagged # "latest", simply overwrite the official tag. Example: # -# docker tag ghcr.io/zephyrproject-rtos/zephyr-build:v0.24.1 +# docker tag ghcr.io/zephyrproject-rtos/zephyr-build:v0.26.4 # ghcr.io/zephyrproject-rtos/zephyr-build:latest # -# "latest" is just a regular tag like "v0.24.1", it may or many not name +# "latest" is just a regular tag like "v0.26.4", it may or many not name # the most recent image. # # To automatically restore the official "latest" tag, just delete it: @@ -54,7 +54,7 @@ main() run_command() { - # zephyr-build:v0.24.13 has /opt/toolchains/zephyr-sdk-0.15.2 + # zephyr-build:v0.26.4 has /opt/toolchains/zephyr-sdk-0.16.1 # https://hub.docker.com/r/zephyrprojectrtos/zephyr-build/tags # # Keep this SDK version identical to the one in @@ -63,7 +63,7 @@ run_command() --workdir /zep_workspace \ $SOF_DOCKER_RUN \ --env REAL_CC --env http_proxy --env https_proxy \ - ghcr.io/zephyrproject-rtos/zephyr-build:v0.24.13 \ + ghcr.io/zephyrproject-rtos/zephyr-build:v0.26.4 \ ./sof/scripts/sudo-cwd.sh "$@" } diff --git a/zephyr/include/rtos/cache.h b/zephyr/include/rtos/cache.h index 716bc55b7a4f..576e1c5bea3d 100644 --- a/zephyr/include/rtos/cache.h +++ b/zephyr/include/rtos/cache.h @@ -6,14 +6,59 @@ #ifndef __ZEPHYR_RTOS_CACHE_H__ #define __ZEPHYR_RTOS_CACHE_H__ -/* TODO: align with Zephyr generic cache API when ready */ #define __SOF_LIB_CACHE_H__ -#include -/* writeback and invalidate data */ -#define CACHE_WRITEBACK_INV 0 +#if !defined(__ASSEMBLER__) && !defined(LINKER) -/* invalidate data */ -#define CACHE_INVALIDATE 1 +#include +#include + +#if defined(CONFIG_XTENSA) && defined(CONFIG_INTEL) + +/* definitions required by xtensa-based Intel platforms. + * + * TODO: if possible, move these to Zephyr. + */ +#define SRAM_UNCACHED_ALIAS 0x20000000 +#define is_cached(address) (!!((uintptr_t)(address) & SRAM_UNCACHED_ALIAS)) + +#endif /* defined(CONFIG_XTENSA) && defined(CONFIG_INTEL) */ + +/* sanity check - make sure CONFIG_DCACHE_LINE_SIZE is valid */ +#if !defined(CONFIG_DCACHE_LINE_SIZE_DETECT) && (CONFIG_DCACHE_LINE_SIZE > 0) +#define DCACHE_LINE_SIZE CONFIG_DCACHE_LINE_SIZE +#else +#if defined(CONFIG_LIBRARY) || defined(CONFIG_ZEPHYR_POSIX) +#define DCACHE_LINE_SIZE 64 +#else +#error "Invalid cache configuration." +#endif /* defined(CONFIG_LIBRARY) || defined(CONFIG_ZEPHYR_POSIX) */ +#endif /* !defined(CONFIG_DCACHE_LINE_SIZE_DETECT) && (CONFIG_DCACHE_LINE_SIZE > 0) */ + +static inline void dcache_writeback_region(void __sparse_cache *addr, size_t size) +{ + /* TODO: return value should probably be checked here */ + sys_cache_data_flush_range((__sparse_force void *)addr, size); +} + +static inline void dcache_invalidate_region(void __sparse_cache *addr, size_t size) +{ + /* TODO: return value should probably be checked here */ + sys_cache_data_invd_range((__sparse_force void *)addr, size); +} + +static inline void icache_invalidate_region(void __sparse_cache *addr, size_t size) +{ + /* TODO: return value should probably be checked here */ + sys_cache_instr_invd_range((__sparse_force void *)addr, size); +} + +static inline void dcache_writeback_invalidate_region(void __sparse_cache *addr, size_t size) +{ + /* TODO: return value should probably be checked here */ + sys_cache_data_flush_and_invd_range((__sparse_force void *)addr, size); +} + +#endif /* !defined(__ASSEMBLER__) && !defined(LINKER) */ #endif /* __ZEPHYR_RTOS_CACHE_H__ */ diff --git a/zephyr/include/rtos/interrupt.h b/zephyr/include/rtos/interrupt.h index 6a8c9890e699..788abfcf3f04 100644 --- a/zephyr/include/rtos/interrupt.h +++ b/zephyr/include/rtos/interrupt.h @@ -52,7 +52,8 @@ static inline void interrupt_unregister(uint32_t irq, const void *arg) */ static inline int interrupt_get_irq(unsigned int irq, const char *cascade) { -#if defined(CONFIG_LIBRARY) || defined(CONFIG_ACE) || defined(CONFIG_ZEPHYR_POSIX) +#if defined(CONFIG_LIBRARY) || defined(CONFIG_ACE) || \ + defined(CONFIG_ZEPHYR_POSIX) || defined(CONFIG_ARM64) return irq; #else if (cascade == irq_name_level2) diff --git a/zephyr/include/sof/compiler_info.h b/zephyr/include/sof/compiler_info.h new file mode 100644 index 000000000000..b07ea72e60d3 --- /dev/null +++ b/zephyr/include/sof/compiler_info.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright 2023 NXP + */ + +#ifndef __SOF_COMPILER_INFO_H__ +#define __SOF_COMPILER_INFO_H__ + +#if defined(__XCC__) + +#include + +#define CC_MAJOR (XTHAL_RELEASE_MAJOR / 1000) +#define CC_MINOR ((XTHAL_RELEASE_MAJOR % 1000) / 10) +#define CC_MICRO XTHAL_RELEASE_MINOR +#define CC_NAME "XCC" +#define CC_DESC " " XCC_TOOLS_VERSION + +#elif defined(__GNUC__) + +#define CC_MAJOR __GNUC__ +#define CC_MINOR __GNUC_MINOR__ +#define CC_MICRO __GNUC_PATCHLEVEL__ +#define CC_NAME "GCC" +#define CC_DESC "" + +#if CC_MAJOR >= 10 +#define CC_USE_LIBC +#endif + +#else + +#error "Unsupported toolchain." + +#endif + +#endif /* __SOF_COMPILER_INFO_H__ */ diff --git a/zephyr/include/sof/lib/cpu.h b/zephyr/include/sof/lib/cpu.h index 41328ee9ebe4..81a8840742b8 100644 --- a/zephyr/include/sof/lib/cpu.h +++ b/zephyr/include/sof/lib/cpu.h @@ -20,10 +20,16 @@ #include -//#include - #include +#if CONFIG_PM + +#include + +void cpu_notify_state_exit(enum pm_state state); + +#endif /* CONFIG_PM */ + /* let the compiler optimise when in single core mode */ #if CONFIG_MULTICORE && CONFIG_SMP diff --git a/zephyr/lib/alloc.c b/zephyr/lib/alloc.c index 4a7f3daa87b2..e6435c7b0b4a 100644 --- a/zephyr/lib/alloc.c +++ b/zephyr/lib/alloc.c @@ -26,7 +26,6 @@ #include #include #include -#include #if CONFIG_SYS_HEAP_RUNTIME_STATS && CONFIG_IPC_MAJOR_4 #include @@ -78,6 +77,18 @@ __section(".heap_mem") static uint8_t __aligned(PLATFORM_DCACHE_ALIGN) heapmem[H #define HEAPMEM_SIZE (256 * 1024) char __aligned(8) heapmem[HEAPMEM_SIZE]; +#elif defined(CONFIG_ARM64) +/* for ARM64 the heap is placed inside the .bss section. + * + * This is because we want to avoid introducing new sections in + * the arm64 linker script. Also, is there really a need to place + * it inside a special section? + * + * i.MX93 is the only ARM64-based platform so defining the heap this way + * for all ARM64-based platforms should be safe. + */ +static uint8_t __aligned(PLATFORM_DCACHE_ALIGN) heapmem[HEAPMEM_SIZE]; + #else extern char _end[], _heap_sentry[]; @@ -201,7 +212,8 @@ static void heap_free(struct k_heap *h, void *mem) if (is_cached(mem)) { mem_uncached = z_soc_uncached_ptr((__sparse_force void __sparse_cache *)mem); - sys_cache_data_flush_and_invd_range(mem, sys_heap_usable_size(&h->heap, mem_uncached)); + sys_cache_data_flush_and_invd_range(mem, + sys_heap_usable_size(&h->heap, mem_uncached)); mem = mem_uncached; } @@ -346,7 +358,6 @@ void rfree(void *ptr) static int heap_init(void) { - sys_heap_init(&sof_heap.heap, heapmem, HEAPMEM_SIZE); #if CONFIG_L3_HEAP diff --git a/zephyr/lib/cpu.c b/zephyr/lib/cpu.c index 99d5b9da83a5..448697bfd6b8 100644 --- a/zephyr/lib/cpu.c +++ b/zephyr/lib/cpu.c @@ -15,7 +15,6 @@ #include /* Zephyr includes */ -#include #include #include @@ -60,12 +59,26 @@ static FUNC_NORETURN void secondary_init(void *arg) #if CONFIG_ZEPHYR_NATIVE_DRIVERS #include #include -#include LOG_MODULE_DECLARE(zephyr, CONFIG_SOF_LOG_LEVEL); extern struct tr_ctx zephyr_tr; +/* notifier called after every power state transition */ +void cpu_notify_state_exit(enum pm_state state) +{ + if (state == PM_STATE_SOFT_OFF) { +#if CONFIG_MULTICORE + if (!cpu_is_primary(arch_proc_id())) { + /* Notifying primary core that secondary core successfully exit the D3 + * state and is back in the Idle thread. + */ + atomic_set(&ready_flag, 1); + } +#endif + } +} + int cpu_enable_core(int id) { /* only called from single core, no RMW lock */ @@ -80,7 +93,13 @@ int cpu_enable_core(int id) return 0; #if ZEPHYR_VERSION(3, 0, 99) <= ZEPHYR_VERSION_CODE - z_init_cpu(id); + /* During kernel initialization, the next pm state is set to ACTIVE. By checking this + * value, we determine if this is the first core boot, if not, we need to skip idle thread + * initialization. By reinitializing the idle thread, we would overwrite the kernel structs + * and the idle thread stack. + */ + if (pm_state_next_get(id)->state == PM_STATE_ACTIVE) + z_init_cpu(id); #endif atomic_clear(&start_flag); diff --git a/zephyr/lib/dma.c b/zephyr/lib/dma.c index ec17c9360051..5bb5b964151b 100644 --- a/zephyr/lib/dma.c +++ b/zephyr/lib/dma.c @@ -78,7 +78,12 @@ SHARED_DATA struct dma dma[] = { .plat_data = { .dir = DMA_DIR_DEV_TO_MEM, .caps = DMA_CAP_HDA, +#ifdef CONFIG_SOC_INTEL_ACE20_LNL + .devs = DMA_DEV_HDA | DMA_DEV_SSP | + DMA_DEV_DMIC | DMA_DEV_ALH, +#else .devs = DMA_DEV_HDA, +#endif /* CONFIG_SOC_INTEL_ACE20_LNL */ .channels = DT_PROP(DT_NODELABEL(hda_link_in), dma_channels), .period_count = HDA_DMA_BUFFER_PERIOD_COUNT, }, @@ -90,7 +95,12 @@ SHARED_DATA struct dma dma[] = { .plat_data = { .dir = DMA_DIR_MEM_TO_DEV, .caps = DMA_CAP_HDA, +#ifdef CONFIG_SOC_INTEL_ACE20_LNL + .devs = DMA_DEV_HDA | DMA_DEV_SSP | + DMA_DEV_DMIC | DMA_DEV_ALH, +#else .devs = DMA_DEV_HDA, +#endif /* CONFIG_SOC_INTEL_ACE20_LNL */ .channels = DT_PROP(DT_NODELABEL(hda_link_out), dma_channels), .period_count = HDA_DMA_BUFFER_PERIOD_COUNT, }, diff --git a/zephyr/lib/pm_runtime.c b/zephyr/lib/pm_runtime.c index ab8adea565c0..99a23c549d30 100644 --- a/zephyr/lib/pm_runtime.c +++ b/zephyr/lib/pm_runtime.c @@ -10,6 +10,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(power, CONFIG_SOF_LOG_LEVEL); @@ -46,7 +47,7 @@ const struct pm_state_info *pm_policy_next_state(uint8_t cpu, int32_t ticks) continue; /* skipping when some ipc task is not finished */ - if (ipc_get()->task_mask) + if (ipc_get()->task_mask || !ipc_platform_poll_is_host_ready()) continue; } @@ -106,3 +107,6 @@ void platform_pm_runtime_put(enum pm_runtime_context context, uint32_t index, void platform_pm_runtime_prepare_d0ix_en(uint32_t index) { } + +void platform_pm_runtime_power_off(void) +{ } diff --git a/zephyr/lib/regions_mm.c b/zephyr/lib/regions_mm.c index 3feb048f0b1e..7921c3c020d3 100644 --- a/zephyr/lib/regions_mm.c +++ b/zephyr/lib/regions_mm.c @@ -22,7 +22,6 @@ struct virtual_memory_heap */ static int virtual_heaps_init(void) { - struct sys_mm_drv_region *virtual_memory_regions = (struct sys_mm_drv_region *)sys_mm_drv_query_memory_regions(); diff --git a/zephyr/wrapper.c b/zephyr/wrapper.c index c508b7c1ff61..2b6102a0de04 100644 --- a/zephyr/wrapper.c +++ b/zephyr/wrapper.c @@ -23,12 +23,16 @@ #include /* Zephyr includes */ +#include #include +#include +#include #include #include #include #include -#include +#include +#include LOG_MODULE_REGISTER(zephyr, CONFIG_SOF_LOG_LEVEL); @@ -108,6 +112,7 @@ void interrupt_unmask(uint32_t irq, unsigned int cpu) { /* TODO: how do we unmask on other cores with Zephyr APIs */ } +#endif void platform_interrupt_set(uint32_t irq) { @@ -118,7 +123,6 @@ void platform_interrupt_clear(uint32_t irq, uint32_t mask) { /* handled by zephyr - needed for linkage */ } -#endif /* * Asynchronous Messaging Service @@ -198,6 +202,20 @@ int task_main_start(struct sof *sof) return 0; } +static int boot_complete(void) +{ +#ifdef CONFIG_IMX93_A55 + /* in the case of i.MX93, SOF_IPC_FW_READY + * sequence will be initiated by the host + * so we shouldn't do anything here. + */ + return 0; +#else + /* let host know DSP boot is complete */ + return platform_boot_complete(0); +#endif /* CONFIG_IMX93_A55 */ +} + int start_complete(void) { #if defined(CONFIG_IMX) @@ -215,9 +233,7 @@ int start_complete(void) pm_policy_state_lock_get(PM_STATE_RUNTIME_IDLE, PM_ALL_SUBSTATES); pm_policy_state_lock_get(PM_STATE_SOFT_OFF, PM_ALL_SUBSTATES); #endif - - /* let host know DSP boot is complete */ - return platform_boot_complete(0); + return boot_complete(); } /* @@ -311,3 +327,13 @@ int poll_for_register_delay(uint32_t reg, uint32_t mask, return 0; } +void k_sys_fatal_error_handler(unsigned int reason, + const z_arch_esf_t *esf) +{ + ARG_UNUSED(esf); + LOG_PANIC(); + + ipc_send_panic_notification(); + + LOG_ERR("Halting system"); +}